About the CSS Loader Generator
What is a CSS loader generator?
A loader is the small piece of motion that tells someone the page hasn't given up on them. Building one in CSS means a shape, a set of keyframes and an animation shorthand, with no image to download and nothing for JavaScript to do. The fiddly part is the keyframes, because getting a spinner to look smooth is mostly a matter of trying numbers until it does.
This tool builds thirty of them, each from a single element. They all run at once in the gallery, in whatever color you've chosen, so you pick the one you want by looking at it rather than by reading a list of names and hoping. Change the size, the color, the thickness or the speed and the big preview reacts, and that preview is running the exact CSS printed below it rather than an approximation of it.
The reason to use this one rather than a gallery of three hundred spinners is what comes with the code. Every loader ships with a prefers-reduced-motion block, so people who have asked their computer to calm animations down get a calmer one instead of the same spin. The markup comes with role="status" and a label, so a screen reader says something rather than nothing. Both take one line, and almost no generator on the web includes either.
How to Use This Tool
- Pick one from the gallery. All thirty are animating, so click the one that looks right. The filter chips narrow it to spinners, dots, bars or shapes if the full set is too much at once.
- Set the size and speed. A cycle somewhere between 0.8 and 1.5 seconds reads as busy without looking frantic.
- Choose the colors. The main color is the moving part. The track is the faint ring or bar behind it, which some types use and others ignore.
- Decide about reduced motion. Slowing down is the safe default, swapping for a fade is the gentlest option, and leaving it out is honest but not kind.
- Copy both boxes. The CSS carries the class, the pseudo-elements and the keyframes. The HTML is one div with the label a screen reader will read.
Common Use Cases
Different waits want different loaders, and picking the wrong one makes an app feel slower than it really is.
- Buttons that are working: a small ring inside the button, with the label swapped out for it, so the click has clearly registered.
- Full page loads: a centered ring or pulse over a dimmed backdrop while the first data arrives.
- Content that is about to appear: the skeleton shimmer, sized to the shape of what's coming. It reads faster than a spinner because the layout stops jumping when the data lands.
- Uploads and long jobs: the indeterminate progress bar, which suggests activity without promising a percentage you can't calculate.
- Chat and comments: the fading dots, which everyone now reads as someone typing.
- Infinite scroll: a small set of bouncing dots at the foot of the list, quiet enough not to compete with the content above it.
Styling the rest of the interface? The CSS Button Generator covers the button the spinner sits in, and the CSS Box Shadow Generator handles the card behind it. The CSS Minifier squeezes the keyframes down before they ship. Or browse all our free developer tools.
Frequently Asked Questions
What is prefers-reduced-motion and why does it matter here?
It's a media query that reports whether someone has turned on the reduce motion setting in their operating system. People do that for vestibular disorders, migraine triggers, motion sickness and plain preference, and it's a real slice of users. A spinner is one of the few animations that arguably has to keep moving, since the movement is the message, so this tool slows it down or swaps it for a fade rather than stopping it. Freezing a spinner would say the page has hung, which is worse than the motion.
Why does my spinner make the page stutter?
Almost always because it animates something that forces the browser to redo layout on every frame, like width, height, top or margin. Every loader here animates transform, opacity, box-shadow or background-position instead, which the compositor can handle without touching layout. If you edit one, stick to those.
Do I need extra divs inside the loader?
No. Every type here is one element. The ones that need more than one moving part use ::before and ::after, which cost nothing in markup, so what you paste is still a single div. That matters more than it sounds, because a loader usually gets dropped into a component whose markup is already busy.
How do I make a screen reader announce the loading state?
The generated markup already does. role="status" makes it a polite live region, and the label gives it something to say. When the element appears, assistive technology announces the label without interrupting whatever is being read. Remove the element when the content arrives, and consider announcing that too, since a silent finish leaves people waiting.
Can I change the color from JavaScript?
Yes, and the tidiest way is a custom property. Replace the color in the generated rule with var(--loader-color), set that variable on a parent, and you can retheme every loader on the page at once. The same trick works for the size if you swap the pixel values for a variable and use calc() for anything derived from it.
Should I show a loader at all?
Not for anything that finishes in under about 200 milliseconds. A spinner that flashes on and off is worse than nothing, because the flicker pulls the eye and by the time you look the answer is already there. The usual fix is a short delay before the loader appears, so quick responses never show one. For anything over a second, show something, or people assume it's broken and click again.
Spinner or skeleton?
Skeleton when you know what the content will look like, which is most of the time in a list or a profile. It shows the shape of what's coming, so the page doesn't jump when the data lands, and studies keep finding that people rate it as faster even when the wait is identical. Spinner when the shape is unknown, the wait is short, or the space is too small for anything else.