Pie charts, loaders and color wheels without any SVG or canvas
conic-gradient() produces color transitions that rotate around a center point instead of running linearly or radially, making it a surprisingly precise tool for pie charts, loading animations and color wheels. Combined with custom properties updated by JavaScript, it becomes a dynamic visualization technique that needs no SVG paths and no canvas drawing logic at all.
Table of Contents
- 1. How conic-gradient() differs from linear-gradient() and radial-gradient()
- 2. A simple pie chart with hard color stops
- 3. Loading animations: a rotating spinner without an image or SVG
- 4. A complete color wheel as a hue selector
- 5. Coupling dynamic values with custom properties and JavaScript
- 6. Practical example: JavaScript updates the progress live
- 7. repeating-conic-gradient(): repeating segment patterns
- 8. Performance compared to SVG and canvas
- 9. Browser support and production readiness
- 10. Summary
- 11. FAQ
1. How conic-gradient() differs from linear-gradient() and radial-gradient()
A linear-gradient() runs along a straight axis, a radial-gradient() radiates concentrically outward from a center point. conic-gradient(), on the other hand, rotates the color transition around a fixed center point, similar to a clock hand sweeping once through a full 360 degrees. Color stops are specified not as a distance from the center, but as an angle, typically in degrees or as a percentage of a full circle.
This angle-based nature makes conic-gradient() inherently suited to anything expressible as a share of a whole, first and foremost pie charts, where every segment's angle is proportional to a data share. Where linear-gradient() and radial-gradient() mostly produce decorative backgrounds, conic-gradient() becomes a genuine tool for data-driven visualization, with no SVG or canvas required.
2. A simple pie chart with hard color stops
The trick to a clean pie chart lies in hard color transitions instead of soft ones: when two consecutive color stops share the same angle, the color jumps abruptly at that point instead of blending smoothly. That lets each segment be defined as an exact angular range with a single, clearly delimited color, just like a classic pie chart from graphics software.
The percentage notation is especially convenient here, since it directly matches a data share: 25% corresponds to a quarter of the circle, 60% to 60 percent of the whole. That makes translating raw percentage values from a dataset into CSS values trivial, with no need to convert to degrees beforehand.
.pie-chart {
width: 200px;
height: 200px;
border-radius: 50%;
background: conic-gradient(
#7c3aed 0% 35%,
#db2777 35% 60%,
#0891b2 60% 85%,
#ca8a04 85% 100%
);
}
3. Loading animations: a rotating spinner without an image or SVG
A common UI element is the classic loading circle that spins while a request runs in the background. With conic-gradient(), this effect can be built purely declaratively: a gradient from transparent to an accent color, applied to a round element with a transparent inner circle, combined with a CSS animation handling the rotation, produces a complete spinner without a single image or SVG file.
The inner transparent circle, usually created via mask or an extra pseudo-element with a white background, turns the full circular area into a thin ring, similar to classic loading indicators. This technique not only saves an external image file, but can also be resized and recolored freely to match the given design system, with no need to export a new asset.
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner {
width: 48px;
height: 48px;
border-radius: 50%;
background: conic-gradient(transparent, #7c3aed);
mask: radial-gradient(farthest-side, transparent calc(100% - 6px), #000 calc(100% - 6px));
animation: spin 0.8s linear infinite;
}
4. A complete color wheel as a hue selector
Because HSL hues themselves cycle from 0 to 360 degrees, a full color wheel can be built with a single conic-gradient() that maps the complete hue circle onto a round element. That fits especially well as a custom hue slider in a color picker widget, where users select a hue directly from the visible wheel by clicking or dragging, with no image or generated graphic needed for it.
The key advantage over a static color wheel image is that saturation and lightness can be controlled independently through additional CSS properties, while the hue continues to be derived exactly from the conic-gradient(). Combined with a radial-gradient() for the saturation transition from center to edge, this even produces a full two-dimensional color picker without an external image file.
.hue-wheel {
width: 180px;
height: 180px;
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%)
);
}
5. Coupling dynamic values with custom properties and JavaScript
The real value for data visualization emerges when the angle values inside conic-gradient() are not hard-coded in the stylesheet, but set via a custom property that JavaScript updates at runtime. A progress bar showing a percentage from an ongoing calculation no longer needs to rewrite the entire CSS, just a single number on the element.
This coupling works so well because conic-gradient() accepts percentage and degree values that can themselves be built from calc() expressions involving custom properties. JavaScript therefore needs neither to regenerate the whole gradient syntax nor to swap DOM elements, it simply calls element.style.setProperty('--progress', '73%'), and the browser handles the rest of the recalculation.
.progress-ring {
--progress: 0%;
width: 120px;
height: 120px;
border-radius: 50%;
background: conic-gradient(#16a34a var(--progress), #e2e8f0 0);
transition: background 0.3s ease;
}
6. Practical example: JavaScript updates the progress live
Building on the previous example, a single line on the JavaScript side is enough to update the progress value, without recreating any DOM elements or rewriting stylesheet rules. This separation between pure data updating in JavaScript and the visual calculation in CSS follows the same principle as the Bash math functions article: logic that used to sit in the script moves to wherever it executes most efficiently.
For animating between two progress values, the transition property on the background property additionally ensures the change happens smoothly rather than abruptly, as long as the browser supports transitions on gradient values. Where that is not the case, the progress simply jumps directly to the new value without animation, but stays functionally correct either way.
<div class="progress-ring" id="ring"></div>
<script type="text/plain">
function setProgress(percent) {
document.getElementById('ring').style.setProperty('--progress', percent + '%');
}
setProgress(73);
</script>
7. repeating-conic-gradient(): repeating segment patterns
Besides conic-gradient(), there is the variant repeating-conic-gradient(), which automatically repeats a defined angular pattern as many times as needed to fill the full circle. That fits especially well for checkerboard-like or spoke-like patterns, where a repeating sequence of colors should form around the center point, for example for decorative background patterns or striped circular warning indicators.
The difference from a conic-gradient() written manually with many color stops lies in the brevity of the declaration: instead of listing every single segment by hand, a single repeating pattern with a fixed angular width is defined, and the browser handles multiplying it around the full circle automatically.
.warning-ring {
width: 60px;
height: 60px;
border-radius: 50%;
background: repeating-conic-gradient(
#f59e0b 0deg 15deg,
#1e293b 15deg 30deg
);
}
8. Performance compared to SVG and canvas
conic-gradient(), as a pure CSS background property, gets rendered by the browser's compositing engine without needing a separate DOM element with SVG paths or a canvas context with manual drawing commands. For simple charts and loaders, that is usually the lighter-weight solution, since no extra rendering context needs to be set up and no JavaScript drawing logic needs to run per frame.
For very complex data visualizations with many interactive segments, per-segment tooltips, or intricate transition animations, conic-gradient() does hit a limit, though, since it is only a background image and offers no individual segments as standalone, event-carrying DOM nodes. For a simple, static or lightly animated pie chart, conic-gradient() remains the leaner, lower-maintenance choice regardless.
9. Browser support and production readiness
conic-gradient() is fully supported by all current versions of Chrome, Edge, Firefox and Safari and has counted as a stable, production-ready feature with no significant restrictions for several years. For most projects, that means no special fallback handling is needed, unlike some of the newer, still partly experimental CSS functions such as calc-size().
Anyone still needing to support very old browser versions can specifically test with @supports (background: conic-gradient(red, blue)) and fall back to a static image for the edge case. In practice, though, that scenario has become rare for conic-gradient() today, since the function is broadly enough supported.
| Use case | Technique | Alternative | Advantage of conic-gradient() |
|---|---|---|---|
| Pie chart | Hard color stops with percentages | SVG paths, canvas | No extra rendering, straight from CSS values |
| Loading animation | conic-gradient + mask + CSS animation | Animated GIF, SVG spinner | No image asset, freely resizable and recolorable |
| Color wheel | HSL hues around the full circle | Static color wheel image | Hue computed exactly, no image compression |
| Progress ring | conic-gradient with custom property | SVG stroke-dasharray | Update via a single CSS variable |
Mironsoft
Modern CSS, layout architecture and rendering performance
CSS that stays maintainable instead of breaking with every change?
We review existing stylesheets for specificity chaos and layout thrashing, then build a CSS architecture with cascade layers, custom properties and modern layout primitives that still makes sense after the tenth feature.
CSS Audit
Systematically uncovering specificity issues, cascade conflicts and unused selectors.
Architecture Refactoring
Introducing cascade layers, custom properties and design tokens cleanly.
Performance Tuning
Fixing layout thrashing, expensive selectors and rendering bottlenecks.
10. Summary
conic-gradient() in CSS: The Essentials at a Glance
Core idea
conic-gradient() rotates colors around a center point based on angle, instead of running linearly or radially.
Pie charts
Hard color stops with percentage values map exact segment boundaries, directly derivable from data shares.
Custom properties
Angle and percentage values can be coupled to JavaScript via var(), for dynamic progress indicators without DOM manipulation.
Limits
For highly interactive charts with per-segment tooltips, SVG remains the more suitable choice, since conic-gradient is only a background image.