How to use the loader generator
- Browse the gallery by spinners, dots, bars, pulses, shapes or progress, then select Customize.
- Pick a variant. Each family has three, such as more dots, a double ring or a different motion.
- Set the size, thickness and speed.
- Choose colors. Some loaders use a second color, and the background color drives the contrast check.
- Copy CSS and HTML, SCSS, a Tailwind component class or a React component.
The markup
<div class="loader" role="status">
<span class="loader__sr">Loading…</span>
<i aria-hidden="true"></i>
</div>
Show the loader when work starts and remove it when it ends. If loading takes long, consider replacing it with a progress message such as “Still working… 60%”.
Worked examples
Example 1: a button that’s saving
Use Ring · Classic at 18px with a 2px thickness and the button’s text color. Place it inside the button before the label, and set aria-busy="true" on the form while saving.
Example 2: a chat app
Use Typing · Bubble: three dots in a soft pill, like messaging apps show while someone types. Keep it small (around 32px) and use your brand’s secondary color.
Example 3: a dashboard loading data
Use Skeleton · Card for each tile while data loads. The layout stays stable, so nothing jumps when content arrives, which helps your CLS score.
Choosing a loader
- Under 1 second: often no loader is needed. Showing one too quickly can make the app feel slower.
- 1–10 seconds: a spinner or dots.
- Longer, measurable work: a determinate progress bar with a percentage.
- Content with a known layout: a skeleton.
Common mistakes
- Showing a spinner too soon. For waits under about a second, a loader flashes and feels slower. Delay it by 300–500 ms.
- No text alternative. Screen reader users need role=“status” with a visually hidden “Loading…” message, as in the markup above.
- Animating layout properties. Animate transform and opacity, not width or margin, to keep the loader smooth and cheap.
- Ignoring reduced motion. Slow or stop the animation under prefers-reduced-motion and rely on the text message instead.
- Spinners for long tasks. If you know the progress, show a progress bar with a percentage; an endless spinner makes long waits feel longer.
Performance
Most loaders animate transform or opacity, which the GPU handles smoothly. A few use background-position or masks, which are still light for a single small element. Avoid running dozens of loaders at once; one per region is enough.
Remember to remove the loader from the DOM when loading finishes, not just hide it visually. Otherwise screen readers may still announce “Loading…”.