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