25 CSS Spinners 02 / 25

Dual Counter-Rotate Ring Spinner

Two concentric rings spin in opposite directions — outer purple and inner pink — with a pulsing radial core, creating a hypnotic, gyroscopic loading indicator.

Pure CSS MIT licensed
Live Demo Open in tab

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

Open in playground

The code

<div class="sp-02">
  <div class="sp-02__wrap">
    <div class="sp-02__outer-track"></div>
    <div class="sp-02__outer"></div>
    <div class="sp-02__inner-track"></div>
    <div class="sp-02__inner"></div>
    <div class="sp-02__core"></div>
  </div>
</div>
.sp-02,.sp-02 *,.sp-02 *::before,.sp-02 *::after{box-sizing:border-box;margin:0;padding:0}
.sp-02{
  --bg:#0d0017;
  --outer:#b44fff;
  --inner:#ff4fa3;
  --outer-track:rgba(180,79,255,0.15);
  --inner-track:rgba(255,79,163,0.15);
  display:flex;
  align-items:center;
  justify-content:center;
  min-height:100vh;
  background:var(--bg);
}
.sp-02__wrap{
  position:relative;
  width:80px;
  height:80px;
}
.sp-02__outer-track{
  position:absolute;
  inset:0;
  border-radius:50%;
  border:4px solid var(--outer-track);
}
.sp-02__outer{
  position:absolute;
  inset:0;
  border-radius:50%;
  border:4px solid transparent;
  border-top-color:var(--outer);
  border-bottom-color:var(--outer);
  animation:sp-02-cw 1.2s linear infinite;
  filter:drop-shadow(0 0 6px var(--outer));
}
.sp-02__inner-track{
  position:absolute;
  inset:14px;
  border-radius:50%;
  border:3px solid var(--inner-track);
}
.sp-02__inner{
  position:absolute;
  inset:14px;
  border-radius:50%;
  border:3px solid transparent;
  border-left-color:var(--inner);
  border-right-color:var(--inner);
  animation:sp-02-ccw 0.9s linear infinite;
  filter:drop-shadow(0 0 6px var(--inner));
}
.sp-02__core{
  position:absolute;
  inset:32px;
  border-radius:50%;
  background:radial-gradient(circle,rgba(180,79,255,0.6),transparent);
  animation:sp-02-pulse 1.2s ease-in-out infinite;
}
@keyframes sp-02-cw{
  to{transform:rotate(360deg)}
}
@keyframes sp-02-ccw{
  to{transform:rotate(-360deg)}
}
@keyframes sp-02-pulse{
  0%,100%{opacity:0.4;transform:scale(0.8)}
  50%{opacity:1;transform:scale(1.2)}
}
@media (prefers-reduced-motion: reduce){
  .sp-02__outer,.sp-02__inner,.sp-02__core{animation:none}
}

How this works

The outer ring is a full-width circle with border-top-color and border-bottom-color set and the sides transparent, animated with sp-02-cw (clockwise). The inner ring — inset by 14px — uses border-left-color and border-right-color and runs sp-02-ccw (counter-clockwise), creating a perpendicular axis visual at matching speed offset.

The centremost element animates opacity and scale via a radial-gradient background that pulses from 0.8 to 1.2 scale, adding depth. All three keyframes are independent so duration tweaks to any layer change the beat without affecting the others.

Customize

  • Swap --outer and --inner colours to any hue pair for brand theming.
  • Change the outer spin speed from 1.2s independently of the inner 0.9s to create different interference patterns.
  • Add a third outermost ring by duplicating the outer track/ring pair with inset:-12px for a triple-layer gyroscope.
  • Replace border-top/bottom with a full 4-side border and use clip-path:inset(0 50% 0 0) for a half-arc look.
  • Increase the core element to inset:20px for a larger glowing centre orb.

Watch out for

  • Two simultaneous infinite rotation animations share the GPU raster layer — test on low-end Android where this can cause jank at 60 Hz.
  • Counter-rotation with animation-direction:reverse on a sibling (not child) element means transforms do not compound — they are independent rotations from the same centre.
  • The core pulsing uses scale inside a @keyframes, which triggers layout in IE 11 (not an issue in modern browsers but worth noting for legacy audit trails).

Browser support

ChromeSafariFirefoxEdge
60+ 12+ 60+ 60+

No cutting-edge features; fully supported in all modern browsers.

Search CodeFronts

Loading…