Free CSS Loader / Spinner Generator

Pick a loading animation, customize colors and speed, and copy the pure CSS code.

Choose a Style

Preview

CSS + HTML Code

How to Use

  1. Pick a loader style from the gallery above.
  2. Customize color, size, speed, and thickness.
  3. Copy the generated CSS + HTML and paste it in your project.

Frequently Asked Questions

Do these loaders use JavaScript?

No! All animations are pure CSS using @keyframes. They work without any JavaScript.

Are these loaders accessible?

Yes, if you add role="status" and an aria-label to the loader element. Users who prefer reduced motion can be accommodated with a prefers-reduced-motion media query.

How It Works

  1. Choose a loader style: select from spinners, dots, bars, rings, pulses, or skeleton loaders.
  2. Customise appearance: adjust color, size, animation speed, and thickness using sliders.
  3. Preview the animation: the loader animates live in the preview area so you can see exactly how it will look.
  4. Copy HTML and CSS: get the minimal HTML markup and CSS required, no JavaScript dependencies needed.

Why Use CSS Loader Generator?

Loading indicators are essential UX elements that communicate activity and prevent users from thinking the page is frozen during async operations. Pure CSS loaders (using only CSS animations without JavaScript or image files) are lightweight, reliable, and render at 60fps using GPU-accelerated transforms. This generator creates production-ready loading spinner code that you can drop directly into your project. All animations use @keyframes with transform and opacity, the two CSS properties that animate without causing layout reflow, ensuring smooth 60fps performance even on low-end devices.

Available Loader Types

A short history of the CSS animation that powers your spinner

The @keyframes rule and the animation shorthand that this generator emits are defined in CSS Animations Module Level 1. The first W3C Working Draft was published 20 March 2009 and the spec finally reached W3C Recommendation on 11 December 2018, nine years later. By then every shipping browser had supported the syntax for years: Safari 4 (June 2009) with the -webkit- prefix, Firefox 5 (June 2011), Internet Explorer 10 (October 2012), and unprefixed by Chrome 43 in April 2015. CSS Animations Module Level 2 is the current Working Draft and adds scroll-driven animations through animation-timeline (shipping in Chrome 115, July 2023; Safari and Firefox followed in late 2024). The rotation in the «spinner» preset comes from CSS Transforms Module Level 1, a separate spec at Candidate Recommendation since February 2019 but universally shipped: transform: rotate(360deg) at 100% inside a @keyframes block is what spins the ring.

Accessibility is not optional: the «Reduce Motion» preference

Every operating system released since 2014 ships a «Reduce Motion» accessibility setting, macOS «Reduce motion» (in Accessibility → Display), iOS «Reduce Motion», Windows «Show animations», Android «Remove animations», GNOME «Enable animations» off. The prefers-reduced-motion media query (defined in Media Queries Level 5, W3C First Public Working Draft November 2017) lets your CSS detect this preference and stop the spinner. Always wrap any spinner in:

@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; }
}

WCAG 2.1 Success Criterion 2.3.3 «Animation from Interactions» (Level AAA, W3C Recommendation 5 June 2018) requires that any motion animation triggered by interaction can be disabled unless the motion is essential. A spinner is rarely essential. WCAG 2.2 (October 2023) inherits the same rule.

For screen readers, wrap the spinner in <div role=\"status\" aria-live=\"polite\"> with a visually-hidden «Loading…» text. When the load completes, replace the contents; the live region announces «Loaded» to assistive tech without yelling. Set aria-busy=\"true\" on the containing region while loading and aria-busy=\"false\" after. This pattern is documented in the W3C ARIA Authoring Practices Guide live-regions chapter.

Why CSS spinners stay smooth at 60 fps

Modern browser rendering pipelines have three stages: layout (computing positions), paint (filling pixels), and composite (combining layers on the GPU). The transform and opacity properties are the only two that skip layout and paint and run purely on the compositor thread. Animating them is essentially free at any framerate. Animating width, height, top, left, margin, or anything that changes the box model forces a full layout-and-paint pass on every frame and quickly drops below 60 fps on low-end devices. Every preset in this generator animates only transform and opacity for this reason. If you need a hint to the browser, will-change: transform (defined in CSS Will Change Module Level 1, W3C Candidate Recommendation 26 April 2022) promotes the element to its own compositor layer; use sparingly because each layer costs GPU memory.

When a spinner is the right answer, and when it is not

In Response Times: The 3 Important Limits (1993, restated 2014), Jakob Nielsen of the Nielsen Norman Group defined three perception thresholds: 0.1 second is «instant», 1 second is the limit for uninterrupted flow of thought, 10 seconds is the limit for keeping the user's attention. Map your loader strategy to these:

Easing functions and what each one feels like

The animation-timing-function property (and the CSS Easing Functions Module Level 1, Candidate Recommendation 6 December 2022) chooses how the value progresses between keyframes:

Common mistakes

More frequently asked questions

Will these spinners work in old browsers?

All modern browsers (Chrome 43+, Firefox 16+, Safari 9+, Edge 12+) support @keyframes and transform without any prefix. Internet Explorer 10 and 11 require the -ms- prefix in some places but otherwise work. IE 9 and below have no CSS animation support: fall back to an animated GIF, or use @supports (animation: spin 1s) to feature-detect.

How do I stop the spinner when content loads?

Either remove the element from the DOM, hide it with display: none or hidden attribute, or pause the animation with animation-play-state: paused. Pausing is cheapest if you might show it again. If you used the ARIA pattern, also set aria-busy=\"false\" on the container and replace the loading text with the loaded state announcement.

Can I customise the spinner colors further than the picker allows?

Yes. The output CSS uses regular hex / rgb / hsl values; replace them with CSS variables (var(--brand-primary)) so the spinner follows your design system. For a dual-color spinner, edit the border-color shorthand: border-color: var(--brand) transparent transparent transparent gives the classic «one-quarter-arc» look.

Why not just use a SVG or Lottie animation?

CSS spinners weigh under 200 bytes, need no extra request, no JavaScript runtime, and render before any external resources load. SVG is great for complex shapes; Lottie is great for designer-authored animations from After Effects. For a generic «something is loading» indicator, CSS is the cheapest tool that does the job correctly.

Is anything tracked or sent to a server?

No. The generator runs entirely in your browser's JavaScript. Your colour picks, size adjustments, and copied CSS never leave the page. Verify in the Network tab of DevTools.

Related Tools