Chase

No dependencies
Code format
React + Tailwind
import type { CSSProperties } from 'react';

const T = 1.6;
const DOTS = 6;

const css = `
  .loader-chase { --ink: light-dark(#373a40, #f1f2f3); position: relative; display: inline-block; font-size: 96px; width: 1em; height: 1em; }
  /* One lap each, easing in and out over the top. Each dot starts a moment after the one ahead,
     so they bunch where the lap is slow and string out where it is fast. */
  .loader-chase__dot { position: absolute; inset: 0; animation: loader-chase-lap ${T}s cubic-bezier(0.62, 0.04, 0.38, 0.96) infinite; animation-delay: var(--d); }
  .loader-chase__dot::before { content: ''; position: absolute; left: 50%; top: 0.06em; width: var(--s); height: var(--s); margin-left: calc(var(--s) / -2); border-radius: 50%; background: var(--ink); opacity: var(--o); }
  @keyframes loader-chase-lap { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) {
    .loader-chase__dot { animation: none; transform: rotate(calc(var(--i) * -20deg)); }
  }
`;

export function Preview() {
  return (
    <>
      <style href="kit-loaders-chase" precedence="kit">
        {css}
      </style>
      <div className="loader-chase" role="status" aria-label="Loading">
        {Array.from({ length: DOTS }, (_, i) => (
          <span
            key={i}
            className="loader-chase__dot"
            style={{ '--d': `${(i * 0.075).toFixed(3)}s`, '--s': `${(0.14 - i * 0.01).toFixed(3)}em`, '--o': (1 - i * 0.13).toFixed(2), '--i': i } as CSSProperties}
            aria-hidden="true"
          />
        ))}
      </div>
    </>
  );
}

Free to use in any project, commercial included. MIT-0, no attribution required. Licence

Install with shadcn

npx shadcn@latest add @movin/loader-chase
Source on GitHub

About this component

Six dots run round a circle, bunching up as they slow over the top and spreading out as they race round the bottom.

Dependencies
None
Difficulty
Beginner
Triggers
continuous, loop, delay stagger
Techniques
keyframes, transition delay stagger, transform only
Reduced motion
Respected
Theme
Light and dark (follows your page's color-scheme)

The root has role="status" and aria-label="Loading"; everything inside it is aria-hidden. Under prefers-reduced-motion the dots rest in a short trailing arc.

More loaders

See all
Coin
Connect
Countdown
Elevator