Snippets /
CSS loading spinner
A lightweight spinning loader — pure CSS, no SVG, no JavaScript.
Default
Large
Quick implementation
.spinner {
width: 2.5rem;
height: 2.5rem;
border: 3px solid oklch(0.88 0.02 260);
border-top-color: oklch(0.5 0.2 260);
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.spinner {
animation-duration: 1.5s;
}
}
Prompt this to your LLM
Paste this into ChatGPT, Claude, or any LLM to create a loading spinner.
Create a pure CSS loading spinner. Use a div with equal width and height
(2.5rem), border: 3px solid with a light oklch color, and override
border-top-color with a vivid oklch accent. Set border-radius: 50%.
Animate with @keyframes rotating from 0 to 360deg using animation:
spin 0.7s linear infinite. Add a @media (prefers-reduced-motion: reduce)
query that slows the animation to 1.5s. Use role="status" and
aria-label="Loading" on the HTML element. Use oklch() for all colors.
Why this matters
Loading indicators are essential feedback during async operations — data fetching, form submissions, page transitions. A CSS-only spinner loads instantly (no image request, no JS execution), weighs virtually nothing, and works even if JavaScript fails. It is one of the most universally needed UI primitives.
The logic
The spinner is a circle (border-radius: 50%) with a uniform border, except one side is a different color (border-top-color). Rotating the element 360 degrees creates the illusion of a spinning arc. linear timing ensures constant speed — easing functions would cause unnatural acceleration. At 0.7s per rotation, the spinner feels brisk without being frantic. The prefers-reduced-motion query slows it down for users who are sensitive to motion — slowing rather than stopping preserves the loading feedback while reducing vestibular discomfort.
Accessibility & performance
Add role="status" to the spinner element so screen readers announce it as a live region. Include aria-label="Loading" to provide a text alternative. If you add visible text like "Loading...", use aria-hidden="true" on the spinner itself to avoid duplicate announcements. The animation runs on the transform property, which is composited on the GPU — it does not trigger layout or paint, making it one of the most performant animations possible. A single spinner has negligible CPU cost.