Overview
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.
When to use it
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.
How it works
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.
Production gotchas
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.
Accessibility
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.
References
Implementation depth
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.