CSS Loader Generator
Make a loading indicator without images or JavaScript. Choose from six animated styles, match the size, colour and speed to your design, and copy a few lines of HTML and CSS.
- Runs in your browser
- No sign-up
- Free to use
Loader
How to use CSS Loader Generator
- Choose the type of loader: ring, dual ring, dots, bars, pulse or ripple.
- Set the colour, size, line thickness and the time one cycle takes.
- Check the preview on a light, dark or patterned background.
- Copy the HTML and the CSS into your project.
CSS Loader Generator features
Six loader styles
Classic spinning ring, dual ring, three bouncing dots, equaliser bars, a pulsing circle and expanding ripples.
No images, no scripts
Everything is drawn with borders, backgrounds and keyframes, a few hundred bytes in total.
Fully adjustable
Size, colour, thickness and speed, each reflected in the code.
Screen-reader friendly
The markup has role="status" and a hidden “Loading…” label.
Reduced-motion aware
A media query slows the animation for visitors who prefer less motion.
Scales cleanly
Loaders are vector shapes, sharp at any size and on any screen.
When to use CSS Loader Generator
- Showing progress while data loads or a form is submitted.
- A loading state inside a button.
- A placeholder while a page section or an image gallery is fetched.
- Replacing an animated GIF spinner with something lighter and sharper.
CSS Loader Generator FAQ
Why use a CSS loader instead of a GIF?
A CSS loader is a few lines of text, needs no extra request, stays sharp at every size and pixel density, and takes its colour from your style sheet, so it works on light and dark backgrounds alike. GIFs are larger, have rough edges on transparent backgrounds and cannot be recoloured.
How do I show and hide the loader?
Add the element to the page when the work starts and remove it when it ends, or toggle the hidden attribute. For a loading state inside a button, place the loader next to the label and disable the button until the request completes.
Why does the markup include role="status" and hidden text?
A spinner is purely visual. role="status" tells assistive technology that the element announces a state, and the visually hidden text gives it something to announce. Without them, a screen-reader user has no indication that anything is happening.
Will the animation slow down my page?
No. The loaders animate only transform and opacity, which browsers handle on the compositor without recalculating layout. They keep running smoothly even while the main thread is busy.
When should I use a spinner and when a skeleton screen?
Spinners suit short waits of uncertain length, such as a button action. For content that takes longer to appear, a skeleton screen, grey placeholders in the shape of the content, feels faster because it shows the layout that is coming. For long operations with measurable progress, use a progress bar.
How do I centre the loader?
Give the parent display: grid and place-items: center, or display: flex with justify-content and align-items set to center. The loader itself is an inline block and needs no positioning of its own.
Telling people that something is happening
Waiting is tolerable when it is acknowledged. A click that produces no visible response makes people click again, or leave. A loading indicator is the simplest acknowledgement: the request was received and work is in progress. Research on perceived performance has long shown that people judge a wait as shorter when they see continuous feedback, even if the actual time is the same.
Pure CSS loaders are built from very little. A spinning ring is a circle with a border, one side in a stronger colour, rotated endlessly by a two-line keyframe rule. Bouncing dots are three small circles running the same animation with staggered delays. Because the shapes are drawn by the browser, they stay sharp at any size and inherit colours from variables or classes, which makes them easy to theme.
Timing shapes how a loader feels. A cycle of about one second reads as steady work. Much faster looks frantic, much slower looks stuck. If an operation usually finishes in under a few hundred milliseconds, consider not showing a loader at all, or delaying its appearance, since a spinner that flashes for an instant is more distracting than helpful.
Accessibility takes two small additions that the generated code already contains. The status role and hidden label make the state perceivable without sight. The reduced-motion query respects visitors who have asked their system to limit animation, by slowing the cycle instead of removing the indicator, since the information that something is loading still matters to them.