WebToolsPlanet
css Tools

CSS Loader Generator

Create pure-CSS loading spinners, dots, and bar animations — no JavaScript or images needed. Customizable colors, sizes, and speeds.

Last updated: March 25, 2026

Client-Side Processing
Input Data Stays on Device
Instant Local Execution

Find this tool useful? Support the project to keep it free!

Buy me a coffee

What is CSS Loader Generator?

A CSS loader is an animated loading indicator built entirely with CSS — no JavaScript event loops, no GIF images, no external icon libraries. They work by combining CSS `@keyframes` animations with CSS `transform` (rotate, scale, translate), `opacity`, and `border` properties. Because browsers handle CSS animations on the compositor thread (a separate thread from JavaScript), CSS loaders remain smooth even when the main JavaScript thread is blocked by data fetching or computation.

The most common CSS loader types: **Spinner** (a circle with a partial border rotating continuously — built with border-radius: 50% and a border with one colored side). **Dots** (3–5 dots pulsing with staggered animation-delay values, creating a wave effect). **Bars** (vertical rectangles scaling up and down sequentially). **Dual Ring** (two counter-rotating concentric circles). **Skeleton** (gray placeholder rectangles that match the shape of loading content, using a CSS shimmer gradient animation). All are GPU-composited animations that run at 60fps without touching the JavaScript main thread.

How to Use CSS Loader Generator

1

Select a loader type from the grid: Spinner, Dots, Bars, Dual Ring, Pulse, or Skeleton

2

Customize the primary color using the color picker (or enter a Hex/HSL value directly)

3

Adjust size with the size slider — the output code uses em units so the loader scales with font-size

4

Set the animation speed: "Slow" (1.5s), "Normal" (0.75s), or "Fast" (0.4s)

5

Click "Copy HTML + CSS" to get both the HTML markup and the complete CSS — drop both into your project

Common Use Cases

  • Adding a spinner to a button while an async form submission is in progress (disabled state indicator)
  • Displaying a full-page loading overlay when navigating between routes in a React/Next.js SPA
  • Using dot loaders in chat applications to indicate "typing..." status for other users
  • Adding skeleton loaders as content placeholders while API data fetches in a dashboard or feed
  • Creating a bar loader for an audio visualizer or file upload progress indicator
  • Adding subtle pulse animations to "loading" placeholder text in a card layout
  • Displaying a spinner in a modal header while async content loads inside the modal
  • Using a skeleton loader in a product grid while e-commerce product data fetches from a CDN

Example Input and Output

A complete pure-CSS spinner implementation:

Generator settings
Type: Spinner
Color: #6366f1 (Indigo)
Size: 40px
Speed: Normal (0.75s)
Generated HTML + CSS
<!-- HTML -->
<div class="loader-spinner"></div>

/* CSS */
.loader-spinner {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 4px solid rgba(99, 102, 241, 0.2);
  border-top-color: #6366f1;
  animation: spin 0.75s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Accessibility: Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  .loader-spinner {
    animation-duration: 2s;
  }
}

Client-Side Processing

All loader code generation runs in your browser. No data is sent to our servers.

CSS Custom Properties for Theming

Define your loader colors as CSS custom properties: .loader { --loader-color: #6366f1; border-top-color: var(--loader-color); }. Then override per component or dark mode: [data-theme="dark"] .loader { --loader-color: #a5b4fc; }. This makes the entire loader color system theme-aware from a single variable change, without requiring class toggles or JavaScript.

will-change Performance Hint

Add will-change: transform to animated elements to hint browsers to promote the element to its own compositor layer before animation starts, reducing animation jank: .loader { will-change: transform; }. Use sparingly — each will-change element consumes GPU memory. For page-level loaders that persist, will-change is worth the memory trade-off. For loaders that appear briefly on hundreds of items simultaneously, omit it and let the browser manage compositing.

Frequently Asked Questions

How do CSS animations work without JavaScript?
CSS `@keyframes` animations are handled by the browser's rendering engine on the compositor thread — completely separate from the JavaScript main thread. The browser interpolates between keyframe states at 60fps (or higher on high-refresh displays) using the GPU for transform and opacity animations. Once declared, the animation runs autonomously. No JavaScript is needed to start, stop, or control it — only CSS class additions/removals are needed, which can be done via CSS :class toggle or minimal JS.
How does the border-trick spinner work?
A CSS spinner uses a div with border-radius: 50% (making it circular). It has a border with all four sides colored in a light, faded version of your spinner color — except one side (border-top-color) which uses the full spinner color. When rotated using @keyframes + transform: rotate(360deg), the single colored side appears to chase the circle around. The key insight: only one border-top-color differs from the other three sides, creating the illusion of a spinning arc.
What is a skeleton loader and when should I use it?
A skeleton loader shows the structural outline of loading content — gray placeholder shapes that match the approximate layout of the incoming data (e.g., a rectangle for a title, three narrower rectangles for body text). A CSS shimmer animation (linear-gradient moving from left to right using @keyframes and background-position) creates the "loading" visual effect. Use skeleton loaders when: (1) you know the shape of the loading content in advance, (2) loading takes 1+ seconds, and (3) you want to reduce layout shift when content arrives. Spinners are better for unknown-shape or short loading states.
How do I handle prefers-reduced-motion for accessibility?
Users with vestibular disorders or motion sensitivity can set "reduce motion" in their OS settings. CSS respects this via the prefers-reduced-motion media query: @media (prefers-reduced-motion: reduce) { .loader { animation: none; } }. Instead of removing the loader entirely, slow the animation significantly (animation-duration: 3s) or use opacity pulsing instead of rotation. CSS loaders without prefers-reduced-motion handling may trigger discomfort or WCAG 2.3.3 failures (Animation from Interactions).
Why use CSS loaders instead of Lottie or GIF animations?
GIFs: large file size (a 100px loading GIF is typically 50–200 KB), fixed colors (cannot adapt to dark mode or theme changes), poor resolution on high-DPI screens. Lottie (SVG animations via a JS library): excellent quality but requires the 60 KB lottie-web JavaScript runtime. CSS loaders: zero runtime overhead, tiny size (< 500 bytes of CSS), infinitely scalable (SVG-like quality at any size), instantly theme-able by changing a CSS custom property color, and no external dependencies needed. For complex branded animations, Lottie wins; for simple loading indicators, CSS is the optimal choice.
Can I animate multiple loaders simultaneously without performance issues?
Yes. CSS animations using only transform and opacity properties are GPU-composited and have minimal CPU impact — running 100+ simultaneous CSS spinners won't cause JavaScript frame drops. Animations using layout-affecting properties (width, height, top, left, padding, margin) trigger browser reflow and should be avoided for animations. A well-built CSS loader that only uses transform: rotate(), opacity, and scale activates zero JavaScript processing and has effectively zero impact on page interactivity.

How This Tool Works

Loader types are defined as CSS template objects: each contains an HTML structure string and a parameterized CSS template string. When the user adjusts color, size, and speed, the template variables are substituted: the color value replaces the {{color}} token, the animation duration replaces {{speed}}, and em-based sizing scales relative to {{size}}. The staggered dot animations use CSS animation-delay: {{index * 0.15}}s applied to each dot element. The final HTML and CSS strings are displayed in the output panel and copied to clipboard.

Technical Stack

CSS @keyframes animationCSS border-radius + border trickCSS animation-delay staggeringprefers-reduced-motion media queryClient-side only