Rings, charts, and highlights with conic-gradient
conic-gradient() arranges color stops around a center point, like slices around a pie rather than bands across a line. Angles describe progress around the turn, which makes the function a natural fit for charts, dials, progress rings, color wheels, and rotating border effects.
The gradient is only an image. The element's dimensions, clipping, masking, and accessible text still need to be designed separately. This separation is what makes the same paint source useful in many components.
Angles, positions, and hard stops
The optional prelude accepts from <angle> and at <position>. Stops can use degrees, percentages, radians, or turns; one turn equals 360 degrees. Repeating a position at the boundary produces a hard edge instead of a blended transition.
For charts, percentages are usually easiest to connect to application data. Keep the same unit throughout a declaration so later edits remain readable.
- from
- Rotates the start angle without changing every stop.
- at
- Moves the gradient center inside or outside the element.
- repeating-conic-gradient()
- Repeats an angular pattern for rays, grids, and segmented rings.
.progress {
--value: 72%;
width: 8rem;
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#38bdf8 0 var(--value), #1e293b 0);
mask: radial-gradient(circle, transparent 58%, #000 59%);
}Cut a clean progress ring
A conic gradient paints the data, while a radial mask removes the center. This produces a real transparent hole, unlike covering the center with a solid-colored pseudo-element. A mask continues to work over photographs and changing themes.
Expose the numeric value as text or with the correct progress semantics. The gradient alone is not an accessible representation of data, and color should not be the only signal for important differences.
Animate a numeric custom property
Gradient images do not reliably interpolate as complete strings. Register a typed custom property with @property, use it as a stop, and animate that number. The browser can then interpolate the angle or percentage directly.
For an indeterminate spinner, rotating the element with transform is simpler and usually cheaper than changing its background image every frame.
@property --sweep {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.spinner {
background: conic-gradient(from var(--sweep), transparent, #a78bfa);
animation: sweep 1s linear infinite;
}
@keyframes sweep { to { --sweep: 360deg; } }Prevent seams and unwanted interpolation
A visible seam can appear where the final stop meets the first. Repeat the first color at 1turn, or place the seam in a low-contrast part of the design. Hard segment boundaries require adjacent stops at the same position.
A circle also requires a square box. Add aspect-ratio: 1 and border-radius: 50%; otherwise the same gradient fills an ellipse-shaped surface even though its angular math is unchanged.
Live catalog examples
These production examples use conic-gradient(). Open any effect to inspect its complete source and experiment in the browser editor.
Browser support
Support notes refer to stable, unprefixed behavior unless a prefix is explicitly listed.
| Feature | Browsers | Note |
|---|---|---|
| conic-gradient() | All modern browsers | Supported without prefixes in current releases. |
| repeating-conic-gradient() | All modern browsers | Useful for procedural patterns and repeated segments. |
| @property | Modern Chromium, Firefox, Safari | Use a static fallback when typed-property animation is optional. |
Common pitfalls
The entire background image is animated
Animate a typed custom property or rotate the element instead of transitioning the gradient string.
Segment boundaries look soft
Repeat the same stop position on both neighboring colors to create a hard edge.
A seam appears at one turn
Match the first and last colors and explicitly close the gradient at
1turn.The ring depends on a solid center cover
Use a radial mask so the hole remains transparent over any background.
Frequently asked questions
- Can conic-gradient create a pie chart?
- Yes, but expose the values as text and use semantic chart markup when the data is meaningful.
- How do I start at the top?
- Use `from -90deg` or rotate the element, depending on how the rest of the design is structured.
- How do I make a donut instead of a pie?
- Apply a radial mask that makes the center transparent.
- Why is my circle stretched?
- The element is not square. Add `aspect-ratio: 1` before applying the circular radius.
Related guides
- maskAlpha masking with CSS maskControl visibility per pixel with gradients and images, including soft edges, real cutouts, and reusable monochrome icons.
- clip-pathCutting shapes with clip-pathClip boxes into responsive geometric shapes and animate them without changing document layout.
- --custom-propertyThemeable effects with CSS custom propertiesTurn repeated values into a clear component API and animate typed custom properties safely with @property.
- mix-blend-modeCompositing layers with CSS blend modesCombine colors and layers with predictable blend boundaries, readable fallbacks, and manageable rendering cost.
Last updated:
All guides