Pure CSS Loaders & patterns #loop #loader

Gyroscope in pure CSS

Three nested rings, each spinning on a different axis — the rotations compound.

  • 44 lines of CSS
  • 9 lines of HTML
  • No JavaScript
  • No dependencies
  • MIT licensed
GitHub

How it works

  1. Three rings, nested. Each spins around one axis only.
  2. Because a child lives inside its parent’s coordinate space, the rotations stack up into complex motion from trivially simple keyframes.
  3. Every level needs transform-style: preserve-3d or the chain flattens there.
  4. Unequal durations keep the pattern from visibly repeating.

Key techniques

  • nested preserve-3d
  • one axis per level
  • different durations

Copy-paste code

HTML 9 lines

<div class="scene">
  <div class="gyro">
    <div>
      <div>
        <b></b>
      </div>
    </div>
  </div>
</div>

CSS 44 lines

.scene {
  perspective: 800px;
}

.gyro,
.gyro div {
  display: grid;
  place-items: center;
  border: 4px solid #8b6cff;
  border-radius: 50%;
  transform-style: preserve-3d;
}

.gyro {
  width: 220px;
  height: 220px;
  animation: gyro-x 6s linear infinite;
}

.gyro div {
  width: 84%;
  height: 84%;
}

.gyro > div {
  border-color: #2ee6d6;
  animation: gyro-y 4s linear infinite;
}

.gyro > div > div {
  border-color: #ff4d9d;
  animation: gyro-x 2.6s linear infinite reverse;
}

.gyro b {
  width: 34%;
  height: 34%;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff, #ffb547 60%);
  box-shadow: 0 0 22px #ffb547;
}

@keyframes gyro-x { to { transform: rotateX(360deg); } }
@keyframes gyro-y { to { transform: rotateY(360deg); } }

Sass source 50 lines

.d-gyro {
  width: 170px;
  height: 170px;
  animation: d-gyro-x 6s linear infinite;

  &,
  div {
    display: grid;
    place-items: center;
    border: 4px solid var(--accent);
    border-radius: 50%;
    transform-style: preserve-3d;
  }

  // Each level spins on its own axis, inside the already-spinning level above it.
  div {
    width: 84%;
    height: 84%;
  }

  > div {
    border-color: var(--accent-2);
    animation: d-gyro-y 4s linear infinite;

    > div {
      border-color: var(--hot);
      animation: d-gyro-x 2.6s linear infinite reverse;
    }
  }

  b {
    width: 34%;
    height: 34%;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, #fff, var(--warm) 60%);
    box-shadow: 0 0 22px var(--warm);
  }
}

@keyframes d-gyro-x {
  to {
    transform: rotateX(360deg);
  }
}

@keyframes d-gyro-y {
  to {
    transform: rotateY(360deg);
  }
}
Standalone snippet · plain CSS, no build step, no dependencies.