AI CSS Animations

3D Flipping Dots Loader

Four dots flip on their vertical axis one after another, turning from solid to hollow ring and back again. Each dot has two faces with backface-visibility hidden, like a row of tiny coins.

Also known as: flip dots loader, coin flip dots, 3d dots animation.

HTML

<div class="ldr-flipping-dots" role="status" aria-label="Loading">
  <span style="--i:0"></span><span style="--i:1"></span><span style="--i:2"></span><span style="--i:3"></span>
</div>

CSS

.ldr-flipping-dots {
  --s: var(--ldr-size, 48px);
  --c: var(--ldr-color, #3b82f6);
  --d: calc(var(--s) / 3.6);
  display: flex;
  gap: calc(var(--s) / 8);
  perspective: calc(var(--s) * 3);
}
.ldr-flipping-dots span {
  position: relative;
  width: var(--d);
  height: var(--d);
  transform-style: preserve-3d;
  animation: ldr-flipping-dots-flip 2s cubic-bezier(0.6, -0.2, 0.3, 1.25) infinite;
  animation-delay: calc(var(--i) * 0.12s - 2s);
}
.ldr-flipping-dots span::before,
.ldr-flipping-dots span::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.ldr-flipping-dots span::before {
  background: var(--c);
}
.ldr-flipping-dots span::after {
  border: calc(var(--s) / 16) solid var(--c);
  background: color-mix(in srgb, var(--ldr-color, #3b82f6) 12%, transparent);
  transform: rotateY(180deg);
}
@keyframes ldr-flipping-dots-flip {
  0%, 12%   { transform: rotateY(0deg); }
  38%, 62%  { transform: rotateY(180deg); }
  88%, 100% { transform: rotateY(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .ldr-flipping-dots, .ldr-flipping-dots *, .ldr-flipping-dots::before, .ldr-flipping-dots::after, .ldr-flipping-dots *::before, .ldr-flipping-dots *::after {
    animation-duration: 3s;
  }
}

Customizing this loader

  • Color: set --ldr-color on the element or a parent. Currently previewing #3b82f6.
  • Size: set --ldr-size. Every dimension in the snippet is derived from it. Currently previewing 64px.
  • Speed: change the duration on the animation shorthand. Delays on the children are relative, so they keep their rhythm.
  • Accessibility: the root carries role="status" and an aria-label so screen readers announce the wait. The reduced-motion rule at the end slows the animation for users who asked for less motion.

Similar loaders