1001Ferramentas
Generators

Animated CSS Loader Generator

Generate full CSS for animated loaders: spinner, dots, progress bar, conic ring.


  

CSS loaders and spinners: feedback during async work

A loader (also called spinner, activity indicator or busy indicator) is a small piece of UI that signals to the user that the interface is doing something they cannot directly observe — fetching data, processing a payment, uploading a file. Without it, a one-second delay feels like a freeze and users start clicking the same button again, hitting reload, or walking away. With it, the same delay feels routine. CSS loaders implement that feedback with pure HTML and a @keyframes rule, so there is no JavaScript runtime cost and no image to download.

The canonical shape is the rotating border ring. You draw a circle with a transparent border, paint one side with a solid colour, and animate transform: rotate from 0deg to 360deg on an infinite linear loop. Because transform is a composited property, the browser can animate it on the GPU without re-running layout or paint, so the spinner stays smooth even when the main thread is busy parsing the JSON it is waiting for.

.spinner {
  width: 32px; height: 32px;
  border: 3px solid #e5e7eb;
  border-top-color: #2563eb;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

Loader families and when to pick each one

  • Spinner / ring — generic "something is happening", indeterminate duration. The default choice for under-3-second waits.
  • Dots — three or four dots scaling or bouncing in sequence. Friendly, often used in chat "typing" indicators.
  • Bars — pulsing vertical bars. Suits audio/equaliser themes and music players.
  • Progress bar — use only when you can measure progress (file upload, multi-step form). The native <progress> element is accessible by default.
  • Skeleton screen — a greyed-out preview of the final layout, ideal for content pages where the structure is predictable.

Performance tips

Animate transform and opacity — never top, left, width or height, which trigger layout on every frame. Add will-change: transform only on long-lived loaders and remove it afterwards; the hint reserves a compositor layer and over-using it can hurt scrolling. conic-gradient lets you draw a colour wheel without SVG, and pairing it with mask hollows out the centre to make a ring.

Accessibility and UX

Every loader should expose role="progressbar" or an aria-label="Loading" so screen readers announce the wait, and the container should set aria-busy="true" until the content arrives. Always wrap the animation in @media (prefers-reduced-motion: reduce) and fall back to a static dot or text — users with vestibular disorders can be physically nauseated by spinning indicators. As for duration: under 200 ms feels instant and needs no loader; 200 ms–1 s a spinner is fine; 1–10 s a progress bar with a percentage; more than 10 s an explicit ETA and the ability to cancel.

FAQ

CSS, SVG or Lottie — which should I use? CSS for simple geometric loops (rings, bars, dots) — smallest payload, no extra request. SVG for shapes with paths CSS cannot draw (logos, mascots). Lottie for After-Effects-grade animations exported as JSON, when polish matters more than weight.

Is there a native HTML alternative? Yes, <progress value="…" max="100"> for determinate progress. It is accessible out of the box and can be styled with CSS.

Why does my loader stutter on mobile? Usually it animates a non-composited property (e.g. background-position or width), or it lives inside a parent that recalculates layout each frame. Switch to transform and make sure the loader's container does not change size while it runs.

How small can a loader be? 16 px is the practical minimum — below that, the user cannot tell a spinner from a static dot. The sweet spot is 24–48 px depending on the surrounding UI.

Related Tools