Pure CSS Text effects #text #faux-3d #loop #sass-loop

Extruded text in pure CSS

A Sass function generates a stack of text-shadows that reads as solid depth.

  • 22 lines of CSS
  • 3 lines of HTML
  • No JavaScript
  • No dependencies
  • MIT licensed

How it works

  1. There is no real depth here — it is many hard-edged text-shadows, each offset 1px further.
  2. Darken each layer slightly and the stack reads as a solid side wall.
  3. Finish with one blurred shadow for the drop shadow on the "ground".
  4. In Sass a @function with a @for loop writes the list for you (see the Sass source tab).

Key techniques

  • text-shadow stack
  • Sass @function
  • rotateY rocking

Copy-paste code

HTML 3 lines

<div class="scene">
  <h1 class="extruded">DEPTH</h1>
</div>

CSS 22 lines

.scene {
  perspective: 800px;
}

.extruded {
  margin: 0;
  font: 900 5rem system-ui;
  letter-spacing: 0.04em;
  color: #fff;
  text-shadow:
    1px 1px 0 #7f63e8, 2px 2px 0 #785ddb,
    3px 3px 0 #7057cd, 4px 4px 0 #6951c0,
    5px 5px 0 #614bb2, 6px 6px 0 #5a45a5,
    7px 7px 0 #523f97, 8px 8px 0 #4b398a,
    14px 18px 18px rgb(0 0 0 / 0.5);
  animation: rock 5s ease-in-out infinite alternate;
}

@keyframes rock {
  from { transform: rotateY(-32deg) rotateX(12deg); }
  to   { transform: rotateY(32deg)  rotateX(-6deg); }
}

Sass source 32 lines

@use 'sass:list';

// Builds "1px 1px 0 c1, 2px 2px 0 c2, …" — each layer a little darker.
@function extrude($depth) {
  $shadows: ();

  @for $i from 1 through $depth {
    $shade: color-mix(in srgb, var(--accent) #{(100 - $i * 5) * 1%}, #000);
    $shadows: list.append($shadows, #{$i}px #{$i}px 0 $shade, comma);
  }

  @return list.append($shadows, #{$depth + 6}px #{$depth + 10}px 18px rgb(0 0 0 / 0.5), comma);
}

.d-text {
  color: #fff;
  font-size: 58px;
  font-weight: 900;
  letter-spacing: 0.04em;
  text-shadow: extrude(12);
  animation: d-text-rock 5s ease-in-out infinite alternate;
}

@keyframes d-text-rock {
  from {
    transform: rotateY(-32deg) rotateX(12deg);
  }

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