- var nrows = 10;
- var ncols = 2*(nrows - 2);
- var n = nrows*ncols;
- var n3gon = 3;
- var c = ['#f5bf55', '#905617', '#56340f', '#e4e1da', '#8c887f', '#47433a'];
- nc = c.length;

style
  - for(var i = 0; i < ncols; i++)
    | .s#{n3gon}prism:nth-child(#{ncols}n + #{i + 1}) { --i: #{i} }
  - for(var i = 0; i < nrows; i++)
    | .s#{n3gon}prism:nth-child(n + #{ncols*i + 1}) { --j: #{i} }
  - for(var i = 0; i < n3gon; i++)
    | .s4gon:nth-child(#{i + 1}) { --k: #{i/n3gon} }
.scene(style=`--nrows: ${nrows}; --ncols: ${ncols}`)
  .grid
    while n--
      div(class=`s${n3gon}prism` style=`--c: ${c[~~(nc*Math.random())]}`)
        - for(var i = 0; i < n3gon; i++)
          .s4gon
        
        
View Compiled
@import 'compass/css3';

$l: 8em;
$h: .5*$l*sqrt(3);
$dc: $l/sin(180deg/3);
$t: 185s;
$f: .1;

@function getPolyPoints(
    $n: 3 /* number of poly vertices */, 
    $oa: -90deg /* angular offset of 1st poly vertex */) {
  
  $ba: 360deg/$n; // base angle corrensponding to 1 poly edge
  $l0: (); // list of points, initially empty
  
  @for $i from 0 through $n {
    $ca: $i*$ba + $oa; // angle current point is at wrt x axis
    $x: calc(50% + (50% - 1px)*#{cos($ca)}); // x coord of current point
    $y: calc(50% + (50% - 1px)*var(--s)*#{sin($ca)}); // y coord of current point
    $l0: $l0, $x $y; // add current point coords to points list
  }
  
  @return $l0
}

body {
  display: grid;
  place-content: center;
  margin: 0;
  height: 100vh;
  background: #262626;
}

.scene {
  overflow: hidden;
  border-radius: 9px;
  box-shadow: 2px 2px 17px #000;
  perspective: 75em;
  perspective-origin: 50% calc(50% - 5*#{$dc})
}

.grid {
  display: grid;
  grid-template: 
    repeat(var(--nrows), $h)/ 
    repeat(var(--ncols), .5*$l);
  margin: -2*$dc (-1.5*$dc);
  margin-right: -(1.5*$dc + .5*$l);
  transform-style: preserve-3d;
  --dir: translatez(-2.25*$dc) rotatex(35deg) rotate(-15deg);
  transform: var(--dir) rotate(0deg);
  animation: r $t linear infinite
}

@keyframes r { to { transform: var(--dir) rotate(1turn) } }

.s3prism {
  --p: 0;
  --s: calc(1 - 2*var(--p));
  position: relative;
  margin: calc(var(--p)*#{$h - $dc}) (-.5*$dc) 0;
  width: $dc; height: $dc;
  transform-style: preserve-3d;
  transform: translateZ(0) scale(.9);
  animation: o 2s ease-in-out calc((var(--i) + var(--j))/(var(--ncols) + var(--nrows) - 1)*-8s) infinite alternate;
  
  &:nth-child(2n) { --p: 1 }
  
  &:before {
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    background: Radial-gradient(transparent 17.5%, 65%, rgba(#000, .5)) var(--c);
    clip-path: polygon(getPolyPoints());
    content: ''
  }
}

@keyframes o { to { transform: translatez(-2*$dc) scale(.9) } }

.s4gon {
  position: absolute;
  top: 50%; left: 50%;
  margin-left: -.5*$l;
  width: $l; height: 2*$dc;
  transform-origin: 50% 0;
  transform: rotate(calc((var(--k) + var(--p)*.5)*1turn)) 
    translatey(calc(#{$h/3} - .5px)) rotatex(-90deg);
  background: Linear-gradient(var(--c), #000);
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.