Pure CSS Shapes & solids #loop #shape

Pyramid in pure CSS

Triangles cut with clip-path, leaned inward by exactly the angle that makes the tips meet.

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

How it works

  1. Each side is a rectangle cut into a triangle with clip-path: polygon(50% 0, 0 100%, 100% 100%).
  2. Like a cube face: rotateY(n × 90deg) translateZ(base / 2) puts it on one side of the base.
  3. Then rotateX with transform-origin: bottom leans it inward. The angle that makes all four tips meet is asin((base / 2) / slant) — 30° when base and slant height are equal.
  4. The floor is a square laid flat with rotateX(90deg).

Key techniques

  • clip-path: polygon()
  • transform-origin: bottom
  • lean angle = asin((base / 2) / slant)

Copy-paste code

HTML 6 lines

<div class="scene">
  <div class="pyramid">
    <i></i><i></i><i></i><i></i>
    <b></b>
  </div>
</div>

CSS 53 lines

.scene {
  perspective: 800px;
}

.pyramid {
  --base: 140px;
  position: relative;
  width: var(--base);
  height: var(--base);        /* slant height = base → lean is exactly 30deg */
  transform-style: preserve-3d;
  animation: pyramid-spin 10s linear infinite;
}

.pyramid i {
  position: absolute;
  inset: 0;
  clip-path: polygon(50% 0, 0 100%, 100% 100%);
  transform-origin: bottom center;
}

.pyramid i:nth-child(1) {
  background: linear-gradient(#ffb547, #b3651a);
  transform: rotateY(0deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}

.pyramid i:nth-child(2) {
  background: linear-gradient(#ffc257, #c27420);
  transform: rotateY(90deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}

.pyramid i:nth-child(3) {
  background: linear-gradient(#ffcf6b, #d18427);
  transform: rotateY(180deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}

.pyramid i:nth-child(4) {
  background: linear-gradient(#ffdb80, #df942f);
  transform: rotateY(270deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}

/* floor */
.pyramid b {
  position: absolute;
  inset: auto 0 0;
  height: var(--base);
  background: #5f3311;
  transform: translateY(50%) rotateX(90deg);
}

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

Sass source 49 lines

@use 'sass:math';

$base: 110px;
$slant: 110px; // height of each triangular face
// Lean each face inward until its tip reaches the centre line.
$lean: math.asin(math.div($base * 0.5, $slant));

.d-pyramid {
  position: relative;
  width: $base;
  height: $slant;
  transform-style: preserve-3d;
  animation: d-pyramid-spin 10s linear infinite;

  i {
    position: absolute;
    inset: 0;
    clip-path: polygon(50% 0, 0 100%, 100% 100%);
    transform-origin: bottom center;

    @for $i from 1 through 4 {
      &:nth-child(#{$i}) {
        background: linear-gradient(hsl(30 + $i * 8, 95%, 62%), hsl(20 + $i * 8, 85%, 30% + $i * 4%));
        transform: rotateY(($i - 1) * 90deg) translateZ($base * 0.5) rotateX($lean);
      }
    }
  }

  // base
  b {
    position: absolute;
    bottom: 0;
    left: 0;
    width: $base;
    height: $base;
    background: hsl(25, 70%, 22%);
    transform: translateY(50%) rotateX(90deg);
  }
}

@keyframes d-pyramid-spin {
  from {
    transform: translateY(8px) rotateX(-18deg) rotateY(0deg);
  }

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