A spinning disc with two rainbow fans sweeping across it, like light catching a CD. The fans are one conic gradient and the center hole is a radial mask, so it needs just one element.
Also known as: spinning cd loader, iridescent disc animation, compact disc spinner.
<div class="ldr-holo-disc" role="status" aria-label="Loading"></div>
.ldr-holo-disc {
--s: var(--ldr-size, 48px);
--c: var(--ldr-color, #3b82f6);
--a: oklch(from var(--c) calc(l + 0.08) c calc(h - 70));
--b: oklch(from var(--c) calc(l + 0.08) c calc(h + 70));
--y: oklch(from var(--c) calc(l + 0.12) c calc(h + 150));
--hole: radial-gradient(closest-side, transparent 22%, #000 calc(22% + 1px));
position: relative;
width: var(--s);
height: var(--s);
border-radius: 50%;
background: color-mix(in srgb, var(--ldr-color, #3b82f6) 20%, transparent);
-webkit-mask: var(--hole);
mask: var(--hole);
}
.ldr-holo-disc::before,
.ldr-holo-disc::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
}
.ldr-holo-disc::before {
background: conic-gradient(transparent 0 5%, var(--a) 11%, var(--c) 15%, var(--b) 19%, var(--y) 23%, transparent 29% 55%, var(--a) 61%, var(--c) 65%, var(--b) 69%, var(--y) 73%, transparent 79%);
animation: ldr-holo-disc-spin 1.4s linear infinite;
}
.ldr-holo-disc::after {
background: radial-gradient(closest-side, color-mix(in srgb, var(--ldr-color, #3b82f6) 45%, transparent) 34%, transparent calc(34% + 1px));
box-shadow: inset 0 0 0 calc(var(--s) / 26) color-mix(in srgb, var(--ldr-color, #3b82f6) 45%, transparent);
}
@keyframes ldr-holo-disc-spin {
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.ldr-holo-disc, .ldr-holo-disc *, .ldr-holo-disc::before, .ldr-holo-disc::after, .ldr-holo-disc *::before, .ldr-holo-disc *::after {
animation-duration: 3s;
}
}The same loader using only Tailwind's built-in animation utilities. No custom keyframes or config needed.
<div class="relative h-12 w-12 rounded-full bg-blue-500/20 [mask:radial-gradient(closest-side,transparent_22%,#000_23%)]" role="status" aria-label="Loading"> <div class="absolute inset-0 animate-spin rounded-full bg-[conic-gradient(transparent_0_5%,#06b6d4_11%,#3b82f6_15%,#d946ef_19%,#f59e0b_23%,transparent_29%_55%,#06b6d4_61%,#3b82f6_65%,#d946ef_69%,#f59e0b_73%,transparent_79%)] [animation-duration:1.4s]"></div> <div class="absolute inset-0 rounded-full bg-[radial-gradient(closest-side,rgba(59,130,246,0.45)_34%,transparent_35%)] shadow-[inset_0_0_0_2px_rgba(59,130,246,0.45)]"></div> </div>
--ldr-color on the element or a parent.
Currently previewing #3b82f6.--ldr-size. Every dimension in the snippet is
derived from it. Currently previewing 64px.animation shorthand.
Delays on the children are relative, so they keep their rhythm.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.