Pure CSS Shapes & solids #loop

Rotating cube in pure CSS

Six faces placed with rotate + translateZ, spun by a single keyframe animation.

  • 38 lines of CSS
  • 6 lines of HTML
  • No JavaScript
  • No dependencies
  • Snippet under MIT
GitHub

How it works

  1. Put perspective on the parent. It is the camera distance — smaller means more dramatic.
  2. Give the cube transform-style: preserve-3d, otherwise its children are flattened into its plane.
  3. Stack all six faces in the same spot, rotate each to face outward, then translateZ by half the side length.
  4. Animate only the cube. The faces ride along for free.
  5. Every length is a multiple of one base unit, --u, so the cube is the same share of a gallery card, the editor and a recording canvas. The side is 120 of those units.

Key techniques

  • transform-style: preserve-3d
  • perspective
  • @keyframes
  • :nth-child places each face

Copy-paste code

HTML 6 lines

<div class="scene">
  <div class="cube">
    <div>1</div><div>2</div><div>3</div>
    <div>4</div><div>5</div><div>6</div>
  </div>
</div>

CSS 38 lines

.scene {
  /* one base unit: every length below is a multiple of it, so the cube is the same share of a
     card, the editor, a full screen and a recording canvas */
  --u: 0.34vmin;
  perspective: calc(800 * var(--u));
}

.cube {
  --s: calc(120 * var(--u));
  position: relative;
  width: var(--s);
  height: var(--s);
  transform-style: preserve-3d;
  animation: spin 9s linear infinite;
}

.cube > * {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font: 700 calc(24 * var(--u)) Inter, system-ui;
  background: rgb(139 108 255 / 0.28);
  border: calc(1 * var(--u)) solid rgb(139 108 255 / 0.8);
}

/* turn each face outward, then push it half a side from the centre */
.cube > :nth-child(1) { transform: rotateY(0deg)   translateZ(calc(var(--s) / 2)); }
.cube > :nth-child(2) { transform: rotateY(90deg)  translateZ(calc(var(--s) / 2)); }
.cube > :nth-child(3) { transform: rotateY(180deg) translateZ(calc(var(--s) / 2)); }
.cube > :nth-child(4) { transform: rotateY(-90deg) translateZ(calc(var(--s) / 2)); }
.cube > :nth-child(5) { transform: rotateX(90deg)  translateZ(calc(var(--s) / 2)); }
.cube > :nth-child(6) { transform: rotateX(-90deg) translateZ(calc(var(--s) / 2)); }

@keyframes spin {
  from { transform: rotateX(-24deg) rotateY(0deg); }
  to   { transform: rotateX(-24deg) rotateY(360deg); }
}
Standalone snippet · plain CSS, no build step, no dependencies.