20 CSS Loaders02 / 20

Pure CSSMIT licensed

CSS Dot Chase Loader

Four dot-based CSS loaders — a staggered bounce chase row, a spinning orbit ring, a hexagonal trail pulse, and animated wave bars — all driven by staggered animation-delay.

Published

Live Demo
Try it

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

The code

<div class="ld-02">
  <div class="ld-02__stage">
    <div class="ld-02__cell"><div class="ld-02__chase"><span></span><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Dot Chase</span></div>
    <div class="ld-02__cell"><div class="ld-02__orbit"><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Orbit Dots</span></div>
    <div class="ld-02__cell"><div class="ld-02__trail"><span></span><span></span><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Trailing Dots</span></div>
    <div class="ld-02__cell"><div class="ld-02__flock"><span></span><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Wave Bars</span></div>
  </div>
.ld-02,
.ld-02 *,
.ld-02 *::before,
.ld-02 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.ld-02 {
  --bg: #0d1117;
  --c1: #f7c948;
  --c2: #f27121;
  --c3: #e94057;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  font-family: 'Segoe UI',sans-serif;
}

.ld-02__stage {
  display: flex;
  gap: 56px;
  flex-wrap: wrap;
  justify-content: center;
  padding: 40px;
}

.ld-02__cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.ld-02__label {
  color: rgba(255,255,255,.4);
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
/* Dot Chase */

.ld-02__chase {
  display: flex;
  gap: 8px;
  align-items: center;
}

.ld-02__chase span {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--c1);
  animation: ld-02-chase 1.2s ease-in-out infinite;
}

.ld-02__chase span:nth-child(1) {
  animation-delay: 0s;
}

.ld-02__chase span:nth-child(2) {
  animation-delay: .15s;
  background: var(--c2);
}

.ld-02__chase span:nth-child(3) {
  animation-delay: .3s;
  background: var(--c3);
}

.ld-02__chase span:nth-child(4) {
  animation-delay: .45s;
  background: var(--c1);
}

.ld-02__chase span:nth-child(5) {
  animation-delay: .6s;
  background: var(--c2);
}

@keyframes ld-02-chase {
  0%,
    80%,
    100% {
    transform: scale(.6);
    opacity: .4;
  }

  40% {
    transform: scale(1.1);
    opacity: 1;
  }
}
/* Orbit dots */

.ld-02__orbit {
  width: 60px;
  height: 60px;
  position: relative;
  animation: ld-02-spin 1.5s linear infinite;
}

.ld-02__orbit span {
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c1);
}

.ld-02__orbit span:nth-child(1) {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}

.ld-02__orbit span:nth-child(2) {
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  background: var(--c2);
}

.ld-02__orbit span:nth-child(3) {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  background: var(--c3);
}

.ld-02__orbit span:nth-child(4) {
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  background: var(--c1);
}

@keyframes ld-02-spin {
  to {
    transform: rotate(360deg);
  }
}
/* Trailing dots */

.ld-02__trail {
  width: 60px;
  height: 60px;
  position: relative;
}

.ld-02__trail span {
  position: absolute;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  animation: ld-02-trail 1.2s ease-in-out infinite;
}

.ld-02__trail span:nth-child(1) {
  background: var(--c1);
  animation-delay: 0s;
  top: 4px;
  left: 26px;
}

.ld-02__trail span:nth-child(2) {
  background: var(--c2);
  animation-delay: .1s;
  top: 10px;
  right: 4px;
}

.ld-02__trail span:nth-child(3) {
  background: var(--c3);
  animation-delay: .2s;
  bottom: 10px;
  right: 4px;
}

.ld-02__trail span:nth-child(4) {
  background: var(--c1);
  animation-delay: .3s;
  bottom: 4px;
  left: 26px;
}

.ld-02__trail span:nth-child(5) {
  background: var(--c2);
  animation-delay: .4s;
  bottom: 10px;
  left: 4px;
}

.ld-02__trail span:nth-child(6) {
  background: var(--c3);
  animation-delay: .5s;
  top: 10px;
  left: 4px;
}

@keyframes ld-02-trail {
  0%,
    100% {
    transform: scale(.4);
    opacity: .3;
  }

  50% {
    transform: scale(1);
    opacity: 1;
  }
}
/* Flocking dots */

.ld-02__flock {
  display: flex;
  gap: 6px;
  align-items: flex-end;
  height: 40px;
}

.ld-02__flock span {
  width: 10px;
  border-radius: 5px;
  background: var(--c2);
  animation: ld-02-flock 1s ease-in-out infinite;
}

.ld-02__flock span:nth-child(1) {
  height: 10px;
  animation-delay: 0s;
}

.ld-02__flock span:nth-child(2) {
  height: 20px;
  animation-delay: .1s;
  background: var(--c3);
}

.ld-02__flock span:nth-child(3) {
  height: 30px;
  animation-delay: .2s;
  background: var(--c1);
}

.ld-02__flock span:nth-child(4) {
  height: 20px;
  animation-delay: .3s;
  background: var(--c3);
}

.ld-02__flock span:nth-child(5) {
  height: 10px;
  animation-delay: .4s;
}

@keyframes ld-02-flock {
  0%,
    100% {
    transform: scaleY(.5);
    opacity: .5;
  }

  50% {
    transform: scaleY(1.3);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ld-02__chase span,
    .ld-02__orbit,
    .ld-02__trail span,
    .ld-02__flock span {
    animation: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Loader from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Dot Chase Loader
Source: https://codefronts.com/motion/css-loader-designs/css-dot-chase-loader/

Four dot-based CSS loaders — a staggered bounce chase row, a spinning orbit ring, a hexagonal trail pulse, and animated wave bars — all driven by staggered animation-delay.
## HTML
```html
<div class="ld-02">
  <div class="ld-02__stage">
    <div class="ld-02__cell"><div class="ld-02__chase"><span></span><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Dot Chase</span></div>
    <div class="ld-02__cell"><div class="ld-02__orbit"><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Orbit Dots</span></div>
    <div class="ld-02__cell"><div class="ld-02__trail"><span></span><span></span><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Trailing Dots</span></div>
    <div class="ld-02__cell"><div class="ld-02__flock"><span></span><span></span><span></span><span></span><span></span></div><span class="ld-02__label">Wave Bars</span></div>
  </div>
```
## CSS
```css
.ld-02,
.ld-02 *,
.ld-02 *::before,
.ld-02 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.ld-02 {
  --bg: #0d1117;
  --c1: #f7c948;
  --c2: #f27121;
  --c3: #e94057;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  font-family: 'Segoe UI',sans-serif;
}

.ld-02__stage {
  display: flex;
  gap: 56px;
  flex-wrap: wrap;
  justify-content: center;
  padding: 40px;
}

.ld-02__cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.ld-02__label {
  color: rgba(255,255,255,.4);
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
/* Dot Chase */

.ld-02__chase {
  display: flex;
  gap: 8px;
  align-items: center;
}

.ld-02__chase span {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--c1);
  animation: ld-02-chase 1.2s ease-in-out infinite;
}

.ld-02__chase span:nth-child(1) {
  animation-delay: 0s;
}

.ld-02__chase span:nth-child(2) {
  animation-delay: .15s;
  background: var(--c2);
}

.ld-02__chase span:nth-child(3) {
  animation-delay: .3s;
  background: var(--c3);
}

.ld-02__chase span:nth-child(4) {
  animation-delay: .45s;
  background: var(--c1);
}

.ld-02__chase span:nth-child(5) {
  animation-delay: .6s;
  background: var(--c2);
}

@keyframes ld-02-chase {
  0%,
    80%,
    100% {
    transform: scale(.6);
    opacity: .4;
  }

  40% {
    transform: scale(1.1);
    opacity: 1;
  }
}
/* Orbit dots */

.ld-02__orbit {
  width: 60px;
  height: 60px;
  position: relative;
  animation: ld-02-spin 1.5s linear infinite;
}

.ld-02__orbit span {
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c1);
}

.ld-02__orbit span:nth-child(1) {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}

.ld-02__orbit span:nth-child(2) {
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  background: var(--c2);
}

.ld-02__orbit span:nth-child(3) {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  background: var(--c3);
}

.ld-02__orbit span:nth-child(4) {
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  background: var(--c1);
}

@keyframes ld-02-spin {
  to {
    transform: rotate(360deg);
  }
}
/* Trailing dots */

.ld-02__trail {
  width: 60px;
  height: 60px;
  position: relative;
}

.ld-02__trail span {
  position: absolute;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  animation: ld-02-trail 1.2s ease-in-out infinite;
}

.ld-02__trail span:nth-child(1) {
  background: var(--c1);
  animation-delay: 0s;
  top: 4px;
  left: 26px;
}

.ld-02__trail span:nth-child(2) {
  background: var(--c2);
  animation-delay: .1s;
  top: 10px;
  right: 4px;
}

.ld-02__trail span:nth-child(3) {
  background: var(--c3);
  animation-delay: .2s;
  bottom: 10px;
  right: 4px;
}

.ld-02__trail span:nth-child(4) {
  background: var(--c1);
  animation-delay: .3s;
  bottom: 4px;
  left: 26px;
}

.ld-02__trail span:nth-child(5) {
  background: var(--c2);
  animation-delay: .4s;
  bottom: 10px;
  left: 4px;
}

.ld-02__trail span:nth-child(6) {
  background: var(--c3);
  animation-delay: .5s;
  top: 10px;
  left: 4px;
}

@keyframes ld-02-trail {
  0%,
    100% {
    transform: scale(.4);
    opacity: .3;
  }

  50% {
    transform: scale(1);
    opacity: 1;
  }
}
/* Flocking dots */

.ld-02__flock {
  display: flex;
  gap: 6px;
  align-items: flex-end;
  height: 40px;
}

.ld-02__flock span {
  width: 10px;
  border-radius: 5px;
  background: var(--c2);
  animation: ld-02-flock 1s ease-in-out infinite;
}

.ld-02__flock span:nth-child(1) {
  height: 10px;
  animation-delay: 0s;
}

.ld-02__flock span:nth-child(2) {
  height: 20px;
  animation-delay: .1s;
  background: var(--c3);
}

.ld-02__flock span:nth-child(3) {
  height: 30px;
  animation-delay: .2s;
  background: var(--c1);
}

.ld-02__flock span:nth-child(4) {
  height: 20px;
  animation-delay: .3s;
  background: var(--c3);
}

.ld-02__flock span:nth-child(5) {
  height: 10px;
  animation-delay: .4s;
}

@keyframes ld-02-flock {
  0%,
    100% {
    transform: scaleY(.5);
    opacity: .5;
  }

  50% {
    transform: scaleY(1.3);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ld-02__chase span,
    .ld-02__orbit,
    .ld-02__trail span,
    .ld-02__flock span {
    animation: none;
  }
}
```

How this works

The dot chase row uses animation-delay stepping at 0.15s per sibling, so each dot hits its peak scale(1.1) just after the previous one, producing a convincing chase. The orbit variant wraps four dots in a container that itself rotate(360deg)s, so the dots maintain their positions while the whole assembly spins — no per-dot positional math needed.

The trailing hexagonal layout positions six dots absolutely using top/left/right/bottom shorthand offsets, each pulsing scale(1)scale(0.4) with cascading delays. The wave bars use scaleY from 0.5 to 1.3 with ease-in-out to mimic a music equaliser feel. All effects rely solely on transform and opacity for 60fps compositing.

Make it yours

  • Increase the number of chase dots by adding <span> elements and extending nth-child delay rules in .15s increments.
  • Adjust the orbit speed via the animation-duration on .ld-02__orbit — use 0.8s for rapid spin or 3s for a slow planet effect.
  • Resize dots uniformly by editing the width and height on .ld-02__chase span — pair with gap changes for proportional spacing.
  • Change the colour ramp by updating the three --c1, --c2, --c3 variables — monochrome with opacity variants creates a minimal look.
  • Convert the wave bars from scaleY to an explicit height animation for browsers that have transform stacking issues with nested flex containers.

Gotchas — read before shipping

  • Applying animation-delay to the orbit container and its children simultaneously causes double-offset timing — animate only the container OR the children, not both.
  • The trailing hexagon requires absolute positioning inside a fixed-size wrapper; percentage-based top/left will misalign dots if the parent size changes.
  • On Safari iOS, animation-direction: alternate combined with staggered delays can produce a first-frame flash — add animation-fill-mode: both to each span.

Browser support

ChromeSafariFirefoxEdge
49+9+44+49+

Universal support — no modern CSS features required beyond keyframe animations and transforms.

Techniques used in this demo

Search CodeFronts

Loading…