Pure CSS Scenes & objects #loop

Laptop lid in pure CSS

The lid hinges on the back edge. Its two sides are separate faces: shell and screen.

  • 49 lines of CSS
  • 5 lines of HTML
  • No JavaScript
  • No dependencies
  • MIT licensed

How it works

  1. First make a floor: rotateX(64deg) rotateZ(28deg) on the base. Everything inside now lives on that tilted plane.
  2. The lid has the same footprint and lies flat on the base when closed. transform-origin: top puts the hinge on the back edge.
  3. A single element has one look from both sides, so the lid is two pseudo-elements: shell on the front, screen pre-flipped with rotateY(180deg), both backface-visibility: hidden.
  4. Open past vertical (104°) and the screen side turns toward the camera.

Key techniques

  • floor plane via rotateX + rotateZ
  • transform-origin: top
  • two-sided element with backface-visibility

Copy-paste code

HTML 5 lines

<div class="scene">
  <div class="laptop">
    <div class="lid"></div>
  </div>
</div>

CSS 49 lines

.scene {
  perspective: 900px;
}

.laptop {
  position: relative;
  width: 220px;
  height: 145px;
  border-radius: 10px;
  background: linear-gradient(#c9cede, #9aa1b8);
  transform-style: preserve-3d;
  transform: translateY(40px) rotateX(64deg) rotateZ(28deg);
}

.lid {
  position: absolute;
  inset: 0;
  transform-origin: top center;
  transform-style: preserve-3d;
  animation: open 3.6s ease-in-out infinite alternate;
}

.lid::before,
.lid::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 10px;
  backface-visibility: hidden;
}

/* outer shell */
.lid::before {
  background: linear-gradient(#b9bfd2, #8e95ad);
  transform: translateZ(1px);
}

/* screen — the other side */
.lid::after {
  border: 7px solid #14161f;
  background: linear-gradient(135deg, #8b6cff, #2ee6d6);
  box-shadow: 0 0 30px #8b6cff;
  transform: rotateY(180deg);
}

@keyframes open {
  0%, 12%   { transform: rotateX(0deg); }
  85%, 100% { transform: rotateX(104deg); }
}

Sass source 56 lines

.d-laptop {
  // This element IS the floor plane: tipped back, then turned.
  position: relative;
  width: 170px;
  height: 112px;
  border-radius: 8px;
  background:
    repeating-linear-gradient(90deg, #0003 0 9px, transparent 9px 12px) 12px 12px / calc(100% - 24px) 52px no-repeat,
    linear-gradient(#c9cede, #9aa1b8);
  transform-style: preserve-3d;
  transform: translateY(34px) rotateX(64deg) rotateZ(28deg);

  // Lid: same footprint, hinged on the back (top) edge, lying flat when closed.
  &__lid {
    position: absolute;
    inset: 0;
    transform-origin: top center;
    transform-style: preserve-3d;
    animation: d-laptop-open 3.6s ease-in-out infinite alternate;

    &::before,
    &::after {
      content: '';
      position: absolute;
      inset: 0;
      border-radius: 8px;
      backface-visibility: hidden;
    }

    // outer shell: visible while closed
    &::before {
      background: linear-gradient(#b9bfd2, #8e95ad);
      transform: translateZ(1px);
    }

    // screen: the other side, visible once open
    &::after {
      border: 6px solid #14161f;
      background: linear-gradient(135deg, var(--accent), var(--accent-2));
      box-shadow: 0 0 30px var(--accent);
      transform: rotateY(180deg);
    }
  }
}

@keyframes d-laptop-open {
  0%,
  12% {
    transform: rotateX(0deg);
  }

  85%,
  100% {
    transform: rotateX(104deg);
  }
}
Standalone snippet · plain CSS, no build step, no dependencies.