AI CSS Animations

3D Sphere Loader

A glossy ball floats above its shadow while the light circles around it, so the highlight sweeps the surface and the shadow swings the opposite way. Two rotating gradient layers, no 3D transforms.

Also known as: glossy ball loader, gradient sphere animation, shaded ball css.

HTML

<div class="ldr-glossy-sphere" role="status" aria-label="Loading">
  <span class="ldr-glossy-sphere-ball"></span>
  <span class="ldr-glossy-sphere-shadow"></span>
</div>

CSS

.ldr-glossy-sphere {
  --s: var(--ldr-size, 48px);
  --c: var(--ldr-color, #3b82f6);
  position: relative;
  width: var(--s);
  height: calc(var(--s) * 1.05);
}
.ldr-glossy-sphere-ball {
  position: absolute;
  top: 0;
  left: 10%;
  width: 80%;
  height: calc(var(--s) * 0.8);
  border-radius: 50%;
  overflow: hidden;
  background: var(--c);
  box-shadow: 0 0 calc(var(--s) / 5) color-mix(in srgb, var(--ldr-color, #3b82f6) 35%, transparent);
  animation: ldr-glossy-sphere-float 2.4s ease-in-out infinite alternate;
}
.ldr-glossy-sphere-ball::before,
.ldr-glossy-sphere-shadow::before {
  content: "";
  position: absolute;
  animation: ldr-glossy-sphere-orbit 3.2s linear infinite;
}
.ldr-glossy-sphere-ball::before {
  inset: -30%;
  background:
    radial-gradient(circle at 36% 34%, color-mix(in srgb, var(--c) 10%, #fff), color-mix(in srgb, var(--c) 55%, #fff) 6%, transparent 22%),
    radial-gradient(circle at 36% 34%, transparent 18%, color-mix(in srgb, var(--c) 55%, #000) 60%);
}
.ldr-glossy-sphere-shadow {
  position: absolute;
  bottom: 0;
  left: 15%;
  width: 70%;
  height: calc(var(--s) * 0.7);
  margin-bottom: calc(var(--s) * -0.28);
  transform: scaleY(0.22);
}
.ldr-glossy-sphere-shadow::before {
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 60% 62%, color-mix(in srgb, var(--ldr-color, #3b82f6) 40%, transparent), transparent 42%);
}
@keyframes ldr-glossy-sphere-orbit {
  to { transform: rotate(360deg); }
}
@keyframes ldr-glossy-sphere-float {
  from { translate: 0 0; }
  to   { translate: 0 calc(var(--s) * -0.05); }
}

@media (prefers-reduced-motion: reduce) {
  .ldr-glossy-sphere, .ldr-glossy-sphere *, .ldr-glossy-sphere::before, .ldr-glossy-sphere::after, .ldr-glossy-sphere *::before, .ldr-glossy-sphere *::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