N
NJHTools

CSS Loaders & Tailwind Spinners

Loading animations you can paste anywhere — Tailwind spinners built from animate-spin, animate-bounce, animate-ping and animate-pulse, plus pure CSS loaders with their own @keyframes.

8 components · live preview · copy as HTML or JSX · free for commercial use

8 CSS loaders to copy

Spinner with Label

CSS Loaders

Loading…

Pure Tailwind (animate-spin). role="status" lets screen readers announce the visible label.

<div role="status" class="inline-flex items-center gap-3 text-sm font-medium text-slate-600">
  <span class="h-5 w-5 animate-spin rounded-full border-2 border-indigo-200 border-t-indigo-600"></span>
  Loading…
</div>

Dual Ring Spinner

CSS Loaders

Loading…

Pure Tailwind: two opposite colored borders on a spinning circle.

<div role="status">
  <span class="block h-10 w-10 animate-spin rounded-full border-4 border-x-transparent border-y-indigo-600"></span>
  <span class="sr-only">Loading…</span>
</div>

Bouncing Dots

CSS Loaders

Loading…

Tailwind animate-bounce with staggered [animation-delay] values. Stops for users who prefer reduced motion.

<div role="status" class="flex items-center gap-1.5">
  <span class="h-2.5 w-2.5 animate-bounce rounded-full bg-indigo-600 [animation-delay:-0.3s] motion-reduce:animate-none"></span>
  <span class="h-2.5 w-2.5 animate-bounce rounded-full bg-indigo-600 [animation-delay:-0.15s] motion-reduce:animate-none"></span>
  <span class="h-2.5 w-2.5 animate-bounce rounded-full bg-indigo-600 motion-reduce:animate-none"></span>
  <span class="sr-only">Loading…</span>
</div>

Pulse Ping

CSS Loaders

Loading…

Pure Tailwind (animate-ping) — a radar-style pulse that also works as a live indicator.

<div role="status" class="relative flex h-10 w-10 items-center justify-center">
  <span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-indigo-400 opacity-75 motion-reduce:animate-none"></span>
  <span class="relative inline-flex h-4 w-4 rounded-full bg-indigo-600"></span>
  <span class="sr-only">Loading…</span>
</div>

Equalizer Bars

CSS Loaders

Loading…

Also copy the CSS tab — this component needs its custom @keyframes to animate.

<div role="status" class="ldr-bars flex h-8 items-center gap-1">
  <div class="h-full w-1.5 rounded-full bg-indigo-600"></div>
  <div class="h-full w-1.5 rounded-full bg-indigo-600"></div>
  <div class="h-full w-1.5 rounded-full bg-indigo-600"></div>
  <div class="h-full w-1.5 rounded-full bg-indigo-600"></div>
  <div class="h-full w-1.5 rounded-full bg-indigo-600"></div>
  <span class="sr-only">Loading…</span>
</div>

SVG Ring Spinner

CSS Loaders

Loading…

A Material-style growing arc: the SVG rotates while the stroke-dasharray stretches and shrinks. Color follows text-* via currentColor.

Also copy the CSS tab — this component needs its custom @keyframes to animate.

<div role="status" class="inline-flex">
  <svg class="ldr-ring h-10 w-10 text-indigo-600" viewBox="0 0 50 50" aria-hidden="true">
    <circle cx="25" cy="25" r="20" fill="none" stroke="currentColor" stroke-width="5" opacity="0.15" />
    <circle class="ldr-ring-arc" cx="25" cy="25" r="20" fill="none" stroke="currentColor" stroke-width="5" stroke-linecap="round" />
  </svg>
  <span class="sr-only">Loading…</span>
</div>

Indeterminate Progress Bar

CSS Loaders

role="progressbar" without aria-valuenow tells assistive tech the progress is indeterminate.

Also copy the CSS tab — this component needs its custom @keyframes to animate.

<div role="progressbar" aria-label="Loading" class="relative h-1.5 w-full max-w-sm overflow-hidden rounded-full bg-indigo-100">
  <div class="ldr-indeterminate absolute inset-y-0 left-0 w-1/3 rounded-full bg-indigo-600"></div>
</div>

Skeleton Card

CSS Loaders

Loading…

Pure Tailwind (animate-pulse). Match the skeleton to your real card's layout to avoid layout shift.

<div role="status" class="w-full max-w-sm animate-pulse rounded-2xl border border-slate-200 bg-white p-5">
  <div class="flex items-center gap-3">
    <div class="h-10 w-10 rounded-full bg-slate-200"></div>
    <div class="flex-1 space-y-2">
      <div class="h-3 w-1/2 rounded bg-slate-200"></div>
      <div class="h-3 w-1/3 rounded bg-slate-200"></div>
    </div>
  </div>
  <div class="mt-5 space-y-2">
    <div class="h-3 rounded bg-slate-200"></div>
    <div class="h-3 w-5/6 rounded bg-slate-200"></div>
  </div>
  <span class="sr-only">Loading…</span>
</div>

Tailwind utilities vs custom @keyframes

Five of these eight loaders need nothing but Tailwind: animate-spin turns a bordered circle into a spinner, animate-bounce with staggered [animation-delay:-0.15s] values makes bouncing dots, animate-ping produces a radar pulse and animate-pulse fades a skeleton card. The others — equalizer bars, the SVG ring spinner and the indeterminate progress bar — ship a short CSS block in the CSS tab. Paste it into your global stylesheet (or a CSS module) along with the HTML; the classes are prefixed ldr- so they will not clash with your own.

To recolor any loader, change the bg-* or border-* color classes. The SVG ring uses stroke="currentColor", so a single text-* class sets its color, and h-* and w-* scale every loader.

Accessible loading states

Every loader has role="status" and visually hidden Loading… text, so screen readers announce it politely without moving focus; the indeterminate bar uses role="progressbar" with an aria-label and no aria-valuenow. Respect users who prefer reduced motion: the bouncing dots and pulse use motion-reduce:animate-none, and the custom CSS loaders slow down under prefers-reduced-motion. Show a loader only after a short delay (around 300 ms) so fast responses don't flash a spinner.

← Back to the full UI Component Library

Frequently Asked Questions

How do I make a spinner in Tailwind CSS?↓

Create a circle with h-8 w-8 rounded-full border-4 border-slate-200 border-t-indigo-600 and add animate-spin. No custom CSS is needed.

Do these CSS loaders need JavaScript?↓

No. Every loader on this page animates with CSS alone — either Tailwind's built-in animate-* utilities or the @keyframes in the CSS tab. You only need JavaScript to show and hide the loader while data loads.

When should I use a skeleton instead of a spinner?↓

Use a skeleton when you know the shape of the content that is coming, such as a card or a list, because it prevents layout shift. Use a spinner for short, shapeless waits such as a button submit.

Last updated: