Loaders
CSS Loading Spinner
A pure-CSS loading spinner built from a rotating SVG arc. Copy the CSS or open it in the editor.
Opens with this animation loaded. Nothing is uploaded — the scene travels in the link.
.spinner {
transform: translate3d(208px, 128px, 0);
width: 64px;
height: 64px;
background: #00000000;
stroke-width: 8;
stroke: #8b7bff;
stroke-dasharray: 30;
stroke-dashoffset: 0;
animation: spinner-anim 1200ms linear 0ms infinite both;
will-change: transform, opacity;
}
@keyframes spinner-anim {
0% {
transform: translate3d(208px, 128px, 0);
}
75% {
transform: translate3d(208px, 128px, 0) rotate(360deg);
}
100% {
transform: translate3d(208px, 128px, 0) rotate(360deg);
}
}
@media (prefers-reduced-motion: reduce) {
.spinner {
animation: none;
transition: none;
}
}Why it is built this way
Most spinner snippets fake the arc with a transparent border, which locks you into a circle and a single colour. This draws a real stroked arc and rotates it, so the thickness, gap and colour are all yours to change. Rotation runs on the compositor, so it costs nothing on the main thread.
What it animates
1 property across 1 CSS declaration. The bar shows when each one is moving.
transformWhat it costs to run
Rotate is handled by the compositor: no layout, no repaint, and the work can run off the main thread. This is the cheap end of CSS animation, which is why it stays smooth on a slow phone where other properties will not.
It runs for 1.20s across 2 keyframe stops, with every property moving over the same window.
A single linear curve on a path. Linear looks wrong on almost anything that starts and stops — but it is exactly right here, because a continuous loop that eases would visibly stutter at the seam where it repeats.
Accessibility
Nothing here hides content — rotate moves over 1.20s and the element is visible throughout. The exported prefers-reduced-motion guard still silences it, which matters most for the looping ones: motion that never stops is the kind that makes people feel unwell.