Pure CSS Shapes & solids #hover #shape

Exploding cube in pure CSS

Hover to blow the faces apart. One custom property moves all six.

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

How it works

  1. Every face uses translateZ(var(--d)) instead of a fixed half-side distance.
  2. Hovering the wrapper changes --d — one declaration moves all six faces.
  3. Because each face has a transition on transform, the change animates even though only a custom property was touched.
  4. Hover is detected on a larger, non-rotating wrapper so the target does not spin out from under the pointer.

Key techniques

  • translateZ(var(--d))
  • transition on a var()-driven transform
  • spin continues underneath

Copy-paste code

HTML 6 lines

<div class="scene" tabindex="0">
  <div class="cube">
    <div></div><div></div><div></div>
    <div></div><div></div><div></div>
  </div>
</div>

CSS 44 lines

.scene {
  --s: 110px;
  --d: calc(var(--s) / 2);     /* distance of each face from the centre */
  display: grid;
  place-items: center;
  width: 300px;
  height: 300px;
  perspective: 800px;
  cursor: pointer;
}

.scene:hover,
.scene:focus {
  --d: 115px;
}

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

.cube > * {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  background: rgb(255 77 157 / 0.35);
  border: 1px solid rgb(255 77 157 / 0.85);
  transition: transform 0.6s cubic-bezier(0.3, 1.5, 0.5, 1);
}

.cube > :nth-child(1) { transform: rotateY(0deg)   translateZ(var(--d)); }
.cube > :nth-child(2) { transform: rotateY(90deg)  translateZ(var(--d)); }
.cube > :nth-child(3) { transform: rotateY(180deg) translateZ(var(--d)); }
.cube > :nth-child(4) { transform: rotateY(-90deg) translateZ(var(--d)); }
.cube > :nth-child(5) { transform: rotateX(90deg)  translateZ(var(--d)); }
.cube > :nth-child(6) { transform: rotateX(-90deg) translateZ(var(--d)); }

@keyframes spin {
  from { transform: rotateX(-24deg) rotateY(0deg); }
  to   { transform: rotateX(-24deg) rotateY(360deg); }
}

Sass source 53 lines

@use 'sass:list';
@use '../mixins' as *;

$turns: (rotateY(0deg), rotateY(90deg), rotateY(180deg), rotateY(-90deg), rotateX(90deg), rotateX(-90deg));

.d-explode {
  --s: 84px;
  --d: calc(var(--s) / 2); // how far each face sits from the centre
  display: grid;
  place-items: center;
  width: 210px;
  height: 210px;
  transform-style: preserve-3d;
  cursor: pointer;

  &:hover,
  &:focus {
    --d: 86px;
  }

  &__cube {
    position: relative;
    width: var(--s);
    height: var(--s);
    transform-style: preserve-3d;
    animation: d-explode-spin 10s linear infinite;
  }

  i {
    position: absolute;
    inset: 0;
    border-radius: 6px;
    @include face(var(--hot), 35%);
    // The transform depends on --d, so changing --d transitions every face at once.
    transition: transform 0.6s cubic-bezier(0.3, 1.5, 0.5, 1);

    @for $n from 1 through 6 {
      &:nth-child(#{$n}) {
        transform: #{list.nth($turns, $n)} translateZ(var(--d));
      }
    }
  }
}

@keyframes d-explode-spin {
  from {
    transform: rotateX(-24deg) rotateY(0deg);
  }

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