Conic-gradient Spinner
A single-element spinner — conic-gradient paints the arc, a radial mask thins the ring without SVG. Three variants: a single quarter arc, balanced dual arcs, and a tapered segmented trace.
A single-element spinner — conic-gradient paints the arc, a radial mask thins the ring without SVG. Three variants: a single quarter arc, balanced dual arcs, and a tapered segmented trace.
Spinner / conic-gradient / mask
Reimplements the CSS spinner with a conic-gradient arc and a radial mask so the ring stays thin without SVG, GIF, or border tricks. Three variants — single quarter arc, balanced dual arcs, and a tapered segmented trace.
Single accent arc + radial mask
A conic-gradient paints one bright 90° arc and a transparent remainder. A radial mask carves the center out so the arc rides a clean ring.
Two opposing arcs + uniform speed
A second arc sits 180° opposite the first. Both share the same hue so the spin reads as a balanced orbit rather than a single head.
Tapered hue stops + slow sweep
Multiple color stops inside the conic fade the arc across its span. The slower duration leans into an ambient look for long-running jobs.
A CSS conic-gradient spinner paints a partial conic arc, cuts the center out with a radial mask, and rotates the ring while nearby text carries the loading status.
1<span class="conic-spinner" aria-hidden="true"></span><span class="conic-spinner-label">Loading preview</span><style>.conic-spinner {width: 4rem;aspect-ratio: 1;display: inline-block;border-radius: 50%;10background:conic-gradient(from 180deg,#67e8f9 0deg 92deg,rgba(103, 232, 249, 0) 92deg 360deg),rgba(103, 232, 249, .16);15-webkit-mask: radial-gradient(circle at center,transparent calc(50% - .52rem),#000 calc(50% - .5rem));mask: radial-gradient(circle at center,transparent calc(50% - .52rem),#000 calc(50% - .5rem));25animation: conic-spinner-recipe-spin 1.1s linear infinite;}27.conic-spinner-label {display: inline-block;margin-inline-start: .65rem;color: #cbd5e1;font: 600 .9rem/1.2 ui-sans-serif, system-ui;}@keyframes conic-spinner-recipe-spin {to { transform: rotate(1turn); }}36@media (prefers-reduced-motion: reduce) {.conic-spinner { animation: none; }}</style>
No. The visual ring should usually be aria-hidden. Put the loading status in adjacent text, aria-busy on the affected region, or a polite live region if the state change needs announcement.
Same masked ring, same rotation animation. A full uniform ring (360°) looks static while spinning — every angle looks the same. A narrow 92° head leaves the rest transparent so the eye catches the moving leading edge.
A conic gradient alone is a filled disk; the radial mask turns it into a spinner ring.
The center has not been masked out. Add a radial mask with a transparent center and opaque outer band so the conic gradient becomes a ring.
A single transformed element is cheap. Performance drops when many large masked gradients or filtered glow layers spin at once, so keep loader rings small and avoid stacking blur-heavy effects.
No. The visual ring should usually be aria-hidden. Put the loading status in adjacent text, aria-busy on the affected region, or a polite live region if the state change needs announcement.
Stop indefinite rotation and leave a static indicator plus readable status text. Do not hide the loading state entirely; motion preference should affect movement, not information.
Same 1.4s rotation, same radial mask, same #67e8f9 leading-edge brightness. BEFORE uses two hard stops — the 92° head is uniformly full opacity, the rest is fully transparent. The result reads as a pie wedge that just happens to be rotating; the eye locks onto BOTH edges equally. AFTER keeps the same 92° span but adds intermediate stops that fade the cyan from 100% at the leading edge down to 0% at the tail. Now the eye reads a bright head with a softer trail behind it — a comet, not a pie slice.
The base conic-gradient paints a solid 92° arc of #67e8f9 over transparent — it works, but the leading and trailing edges are abrupt, so the spinner reads as "rotating pie slice" rather than "moving head with a trail behind it". Real production spinners taper the head so the leading edge stays bright while the trailing portion fades. Same conic-gradient property, same mask, same rotation animation — just richer color stops inside the head: 100% opacity at the leading edge, then several stops fading to transparent across the 92° span. The change is purely additional stops in the same gradient declaration.
Append these rules inside the <style> block from the base snippet above.
/* Advanced: tapered arc head — extends the base recipe.Same conic-gradient property, same radial mask cut-out, samerotation animation. The arc head now contains multiple stops thatfade the cyan opacity from 100% at the leading edge down to 0% atthe tail, producing a "comet trail" look rather than a hard piewedge. No structural change — just denser color stops in the samegradient. */.conic-spinner {background:conic-gradient(from 180deg,rgba(103, 232, 249, 1) 0deg,rgba(103, 232, 249, .85) 30deg,rgba(103, 232, 249, .55) 60deg,rgba(103, 232, 249, .25) 80deg,rgba(103, 232, 249, 0) 92deg,rgba(103, 232, 249, 0) 360deg),rgba(103, 232, 249, .16);}
Conic-gradient spinners paint a rotating arc with one CSS property and one element — no SVG, no GIF, no border tricks. A conic-gradient colors a single bright arc and a transparent remainder; a radial-gradient mask carves the centre out so the spinner reads as a ring. The whole element rotates on a linear keyframe.
Reach for conic spinners on form-submit loading states, async page transitions, and anywhere a small indeterminate progress indicator needs to fit inside a button or chip. Skip them for long-running operations — a spinner is an unresolved promise; users tolerate it for seconds, not minutes. Use a determinate progress bar past that point.
The element gets background: conic-gradient(from 0deg, transparent 270deg, var(--accent) 360deg) — a 90-degree bright arc with transparent remainder. To carve out the center, apply mask: radial-gradient(circle, transparent 60%, black 61%) which hides the inner disc and leaves only an outer ring. Then animation: spin 1s linear infinite with a @keyframes spin { to { transform: rotate(360deg) }
} rule rotates the whole element. Linear timing is non-negotiable — ease curves make spinners look like they are hesitating.
Spinning a background-only element rotates the gradient too — this is what you want. But spinning a layered element with an internal label or icon also rotates the label; either keep the spinner as a leaf element or counter-rotate the inner content. The CSS mask property still needs the -webkit-mask prefix for Safari iOS as of 2026. Hard-edged mask transitions can banding on retina; use black 61% rather than black 60.1% for the cut-off — a wider transition smooths the edge.
Wrap the spinner in a container with role="status" + aria-label="Loading" so screen readers announce its presence. Under prefers-reduced-motion: reduce swap the infinite spin for a single static frame — the visual indicator still shows “working” without the continuous rotation that can trigger vestibular issues. Avoid spinners shorter than 600ms per revolution; faster rates feel anxious.
A conic-gradient spinner is strongest as a single-element loader. The gradient paints the arc, a radial mask cuts the hole, and transform rotation supplies motion without SVG markup.
Spinners communicate waiting, not progress. Use them for unknown durations, prefer native progress for known values, and stop rotation under reduced motion while keeping a static loading indicator visible.