Conic Gradient CSS: Pie Charts, Color Wheels and Angled Fills
Master CSS conic-gradient() to build pure-CSS pie charts, color wheels, and angled fills — no SVG, no canvas, just one property and a fistful of color stops.
What Even Is a Conic Gradient?
Most developers know linear-gradient() and radial-gradient() by heart. Conic is the third one — and honestly it gets slept on more than it deserves. Where linear sweeps left-to-right and radial expands outward from a center point, conic-gradient() rotates color stops around a center point. Think of a clock face, or a spinning pie chart. The color changes as you go around the circle, not toward or away from it.
The full syntax looks like this: background: conic-gradient(from 0deg at 50% 50%, red, yellow, green, blue, red). The from keyword sets the starting angle (0deg = 12 o'clock by default if you omit it), the at keyword positions the center, and then you list your color stops just like you would in any other gradient. Chrome shipped it in version 69 back in 2018. Firefox held out until 83. These days it's in every browser you care about.
Quick aside: conic gradients are rendered as CSS <image> values, meaning you can use them anywhere you'd use a linear-gradient — background, background-image, mask-image, border-image. That flexibility is where things get interesting.
Worth noting: you can also use repeating-conic-gradient(), which tiles the color sequence repeatedly around the circle — great for checkerboard patterns, radial striping, or those hypnotic spinning pinwheel effects you see on loading screens.
The Syntax in Full, No Fluff
Here's the formal signature: conic-gradient( [ from <angle> ]? [ at <position> ]?, <color-stop-list> ). Every part in square brackets is optional. Drop the from and it starts at 0deg (top). Drop the at and the center defaults to 50% 50%. The color stop list works exactly like linear/radial — you can use any CSS color and optionally pin a stop to a specific angle in degrees, turns, or percentages.
/* Simplest possible conic — full rainbow wheel */
.color-wheel {
width: 200px;
height: 200px;
border-radius: 50%;
background: conic-gradient(
hsl(0, 100%, 50%),
hsl(60, 100%, 50%),
hsl(120, 100%, 50%),
hsl(180, 100%, 50%),
hsl(240, 100%, 50%),
hsl(300, 100%, 50%),
hsl(360, 100%, 50%)
);
}That gives you a smooth color wheel. Now pin your stops with explicit angles to get hard-edged slices instead of smooth transitions — which is the trick behind pure-CSS pie charts:
``css
/* Hard-stop pie chart: 40% red, 35% blue, 25% green */
.pie {
width: 200px;
height: 200px;
border-radius: 50%;
background: conic-gradient(
#ef4444 0deg 144deg,
#3b82f6 144deg 270deg,
#22c55e 270deg 360deg
);
}
``
The trick is listing the same angle twice — once as the end of the previous stop and once as the start of the next. That creates a zero-width transition, which is a hard edge.
In practice, I almost always prefer turn units over degrees for pie math. 0.4turn is just easier than 144deg when you're thinking in percentages. Your call — both work identically.
Pure CSS Pie Charts Without a Single Line of JavaScript
This is the headline use case. Before conic-gradient(), CSS pie charts were either a gnarly hack with clip-path transforms, an SVG file you had to maintain separately, or a JavaScript charting library that added 50 KB to your bundle. Now you need exactly one property.
/* Dynamic pie chart using CSS custom properties */
.pie-chart {
--p1: 0.35; /* 35% — slice 1 */
--p2: 0.45; /* 45% — slice 2 */
/* remaining 20% is slice 3 */
width: 180px;
height: 180px;
border-radius: 50%;
background: conic-gradient(
#6366f1 0turn calc(var(--p1) * 1turn),
#f59e0b calc(var(--p1) * 1turn) calc((var(--p1) + var(--p2)) * 1turn),
#10b981 calc((var(--p1) + var(--p2)) * 1turn) 1turn
);
}Combine that with a bit of JavaScript to update the custom properties from real data and you have a fully animated, pure-CSS data viz component. Add transition: --p1 0.4s ease, --p2 0.4s ease and the slices animate smoothly between values. One caveat: CSS custom property transitions on gradient values require @property registration in 2026 — Chrome and Edge support it, Safari 17.4+, Firefox still partial. Define your properties with @property to get the smooth animation everywhere it's supported.
@property --p1 {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
@property --p2 {
syntax: '<number>';
inherits: false;
initial-value: 0;
}If you're building a full dashboard with multiple chart types, the gradient generator on Empire UI can help you prototype color palettes quickly before you wire in real data. And if you want pre-built chart wrapper components, the Empire UI library has card and stat components that pair cleanly with custom CSS charts like these.
Color Wheels, Checkerboards, and the Repeating Variant
Color wheels are the other killer demo. A smooth HSL wheel needs no angle pins — just start at hsl(0, 100%, 50%) and end at hsl(360, 100%, 50%) and CSS interpolates everything in between. Clip it with border-radius: 50% and you're done. Genuinely one of those things that used to require a canvas element and a few dozen lines of JavaScript.
``css
.hsl-wheel {
width: 240px;
height: 240px;
border-radius: 50%;
background: conic-gradient(
in hsl,
hsl(0 100% 50%),
hsl(360 100% 50%)
);
}
`
The in hsl` hint (part of CSS Color Level 4) tells the browser to interpolate through HSL space instead of sRGB. Without it, some diagonal transitions look muddy. Chrome 111+ and Safari 16.2+ respect it — for older targets just list 6–8 explicit HSL stops manually.
Repeating conic gradients open a totally different door. A checkerboard pattern used to need SVG or a background-image hack with two linear-gradient() declarations. With repeating-conic-gradient() you can do it in one line:
``css
.checkerboard {
background: repeating-conic-gradient(
#1e1e2e 0deg 90deg,
#313244 90deg 180deg
) 0 0 / 40px 40px;
}
`
That 0 0 / 40px 40px is the background-position and background-size shorthand. Change 40px` to any value and the tile scales. Dead simple.
Honestly, the repeating variant is where I see the most creative use. Radial stripe loaders, color swatch pickers, CSS-only spinner animations — all achievable with a one-property background. If you're building something visually expressive and want to see how conic patterns complement other CSS backgrounds, check out the aurora background guide — stacking a semi-transparent conic gradient over an animated aurora is a surprisingly great combo.
Angled Fills, Borders, and Using Conic in Unexpected Places
Most tutorials stop at pie charts and color wheels. The less-obvious stuff is more useful day-to-day. Conic gradients make excellent angled fills for section dividers — not the same as linear-gradient diagonals, because you can anchor the sweep point to a corner and get a hard angular slice:
``css
.angled-hero {
background: conic-gradient(
from 0deg at 0% 100%,
#7c3aed 0deg 45deg,
transparent 45deg
);
}
`
That's a single triangular fill in the bottom-left corner. No clip-path`, no pseudo-element, no SVG. One declaration.
Gradient borders are another gem. The border-image property accepts <image> values, which means your conic gradient can be a border:
``css
.rainbow-border {
border: 3px solid transparent;
border-image: conic-gradient(
from var(--angle),
#f59e0b, #ef4444, #8b5cf6, #3b82f6, #f59e0b
) 1;
animation: spin 3s linear infinite;
}
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
@keyframes spin {
to { --angle: 360deg; }
}
`
That's a spinning rainbow border with pure CSS animation — no JavaScript, no canvas, no SVG filter. The @property` registration is what enables the CSS custom property to animate smoothly through angle values. If you want to explore similar border effects without writing them yourself, Empire UI's components include several animated border styles you can copy directly.
Worth noting: mask-image: conic-gradient(...) lets you create angular reveal animations. Mask a div with a conic gradient sweeping from 0 to 360 degrees and you get a clock-hand reveal — pure CSS progress indicators that used to need JavaScript counting frames.
Look, there's a reason UI designers started gravitating toward conic gradients after 2020. They solve a class of visual problems — circular fills, angular clipping, radial patterns — that previously had no clean CSS-native answer. The box shadow generator and gradient generator tools on Empire UI won't generate conic gradients directly (yet), but they're great companions for figuring out depth and color before you wire up the conic layer.
Browser Support, Gotchas, and Fallbacks
Full conic-gradient() support: Chrome 69+, Safari 12.1+, Firefox 83+, Edge 79+. repeating-conic-gradient() has the same baseline. The in hsl color interpolation hint is newer — Chrome 111, Safari 16.2, Firefox 113. @property for animating custom properties is Chrome/Edge 85+, Safari 17.4, Firefox still limited as of mid-2026.
The one real gotcha is that hard-stop pie charts can show a 1px antialiased fringe at slice edges on some displays, especially at non-round percentages. The fix is to offset your hard stops by 0.5deg:
``css
/* Before (may show fringe) */
conic-gradient(red 0deg 144deg, blue 144deg 360deg)
/* After (cleaner edge) */
conic-gradient(red 0deg 143.5deg, blue 144.5deg 360deg)
``
It's a 1-degree gap filled with a micro-transition. Barely visible but it eliminates the fringe on retina displays.
For browsers that genuinely can't render conic gradients — we're talking IE 11 or old Android WebViews — wrap your declaration with @supports:
``css
.pie {
background: #6366f1; /* flat fallback */
}
@supports (background: conic-gradient(red, blue)) {
.pie {
background: conic-gradient(#6366f1 0 0.35turn, #f59e0b 0.35turn 0.8turn, #10b981 0.8turn 1turn);
border-radius: 50%;
}
}
``
Keep the fallback meaningful — a solid fill in your primary brand color is better than a broken chart.
One more thing — if you're building a design system and want consistent conic gradient tokens across components, store your angle and color values in CSS custom properties at the :root level. That way a single source-of-truth change cascades everywhere, same pattern you'd use with any other CSS variables system.
Conic Gradients in Real UI — Practical Recipes
Theory is great but let's talk about what actually ships. The most common production uses I see are: donut charts (conic gradient + inner circle using box-shadow or a pseudo-element), progress rings (mask-image technique), loading spinners (rotating conic gradient), and section background textures (repeating conic for grid/checker patterns).
Donut chart recipe — apply the pie background, then cover the center with a pseudo-element:
``css
.donut {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background: conic-gradient(
#6366f1 0 0.6turn,
#e2e8f0 0.6turn 1turn
);
}
.donut::after {
content: '';
position: absolute;
inset: 30px;
border-radius: 50%;
background: #0f172a; /* match your page background */
}
`
The inset: 30px creates a 30px ring width. Drop your percentage label in a position: absolute` child centered inside the donut.
For spinner/loader use cases, the cleanest approach is a conic gradient that fades to transparent, then rotates:
``css
.spinner {
width: 48px;
height: 48px;
border-radius: 50%;
background: conic-gradient(transparent 0deg, #6366f1 360deg);
mask: radial-gradient(circle, transparent 40%, black 41%);
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
`
That mask` declaration cuts out the center, leaving just the ring. No border tricks needed.
If you're combining conic patterns with other expressive styles — say a glassmorphism card floating over a conic gradient background — the glassmorphism components on Empire UI slot in perfectly. The frosted-glass card over a spinning color wheel background is one of those combinations that looks way more complex than it actually is to build.
FAQ
Yes, but you need @property to register any custom properties used in the gradient so the browser knows how to interpolate them. Register the angle or numeric value with a syntax declaration and then transition or animate it normally. Chrome and Edge fully support this; Safari from 17.4; Firefox support is still partial as of 2026.
List the same angle value twice in a row — once as the end of one stop and once as the start of the next. For example conic-gradient(red 0deg 144deg, blue 144deg 360deg) creates a zero-width transition at 144deg, which renders as a hard edge. Offset by 0.5deg each side to eliminate antialiasing fringe on retina screens.
Yes — Chrome 69+, Firefox 83+, Safari 12.1+, and Edge 79+ all support conic-gradient() and repeating-conic-gradient(). The newer in hsl color interpolation hint requires Chrome 111+ or Safari 16.2+. Use @supports for fallbacks if you still need IE11 or old Android WebView support.
Radial gradients emanate outward from a center point — color changes with distance from the center. Conic gradients rotate around a center point — color changes with the angle. Think radial = rings; conic = pie slices or a clock face.