AI CSS Animations

Nested Squares Spinner

Three square outlines, one inside the next, each making a full eased turn a beat after the one around it, so the set twists into a spiral and unwinds. Stock animate-spin covers it in Tailwind.

Also known as: concentric squares spinner, square spiral loader, rotating squares loader.

HTML

<div class="ldr-nested-squares" role="status" aria-label="Loading">
  <span></span><span></span><span></span>
</div>

CSS

.ldr-nested-squares {
  --s: var(--ldr-size, 48px);
  --c: var(--ldr-color, #3b82f6);
  position: relative;
  width: var(--s);
  height: var(--s);
}
.ldr-nested-squares span {
  position: absolute;
  inset: 0;
  border: calc(var(--s) / 12) solid var(--c);
  border-radius: calc(var(--s) / 24);
  animation: ldr-nested-squares-spin 1.6s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.ldr-nested-squares span:nth-child(2) {
  inset: calc(var(--s) / 6);
  border-color: color-mix(in srgb, var(--ldr-color, #3b82f6) 70%, transparent);
  animation-delay: 120ms;
}
.ldr-nested-squares span:nth-child(3) {
  inset: calc(var(--s) / 3);
  border-color: color-mix(in srgb, var(--ldr-color, #3b82f6) 40%, transparent);
  animation-delay: 240ms;
}
@keyframes ldr-nested-squares-spin {
  to { transform: rotate(360deg); }
}

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

Tailwind CSS version

The same loader using only Tailwind's built-in animation utilities. No custom keyframes or config needed.

<div class="relative h-12 w-12" role="status" aria-label="Loading">
  <span class="absolute inset-0 animate-[spin_1.6s_cubic-bezier(0.65,0,0.35,1)_infinite] rounded-sm border-4 border-blue-500"></span>
  <span class="absolute inset-2 animate-[spin_1.6s_cubic-bezier(0.65,0,0.35,1)_infinite] rounded-sm border-4 border-blue-500/70 [animation-delay:120ms]"></span>
  <span class="absolute inset-4 animate-[spin_1.6s_cubic-bezier(0.65,0,0.35,1)_infinite] rounded-sm border-4 border-blue-500/40 [animation-delay:240ms]"></span>
</div>

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