Text effects
Extruded text
Pure CSSA Sass function generates a stack of text-shadows that reads as solid depth.
The extrusion is a Sass-generated shadow stack whose direction follows your pointer.
Your edited version
calc(var(--dx) * Npx).--dx / --dy, and the shadow swings away from it.text-shadow with calc(var() × n)Sass @functionpointer → custom properties<div class="scene">
<h1 class="lit">SHADOW</h1>
</div>
.scene {
display: grid;
place-items: center;
width: 100vw;
height: 100vh;
}
.lit {
--dx: 0.7; /* direction — overwritten from JS */
--dy: 0.7;
margin: 0;
font: 900 4.5rem system-ui;
color: #fff;
text-shadow:
calc(var(--dx) * 1px) calc(var(--dy) * 1px) 0 #e6a340,
calc(var(--dx) * 2px) calc(var(--dy) * 2px) 0 #d99a3c,
calc(var(--dx) * 3px) calc(var(--dy) * 3px) 0 #cc9139,
calc(var(--dx) * 4px) calc(var(--dy) * 4px) 0 #bf8835,
calc(var(--dx) * 5px) calc(var(--dy) * 5px) 0 #b37f32,
calc(var(--dx) * 6px) calc(var(--dy) * 6px) 0 #a6762e,
calc(var(--dx) * 7px) calc(var(--dy) * 7px) 0 #996d2b,
calc(var(--dx) * 8px) calc(var(--dy) * 8px) 0 #8c6327,
calc(var(--dx) * 9px) calc(var(--dy) * 9px) 0 #805a24,
calc(var(--dx) * 10px) calc(var(--dy) * 10px) 0 #735120,
calc(var(--dx) * 22px) calc(var(--dy) * 22px) 20px rgb(0 0 0 / 0.5);
}
const scene = document.querySelector('.scene');
const text = document.querySelector('.lit');
scene.addEventListener('pointermove', (e) => {
const r = scene.getBoundingClientRect();
const x = (e.clientX - r.left) / r.width - 0.5;
const y = (e.clientY - r.top) / r.height - 0.5;
// the pointer is the light, so the shadow falls the other way
text.style.setProperty('--dx', -x * 2);
text.style.setProperty('--dy', -y * 2);
});
@use 'sass:list';
// Same shadow-stack idea as the extruded text, but every offset is multiplied by
// --dx / --dy at runtime, so JS can swing the whole extrusion with two numbers.
@function lit-extrude($depth) {
$shadows: ();
@for $i from 1 through $depth {
$shade: color-mix(in srgb, var(--warm) #{(95 - $i * 5) * 1%}, #000);
$shadows: list.append($shadows, calc(var(--dx) * #{$i}px) calc(var(--dy) * #{$i}px) 0 $shade, comma);
}
@return list.append($shadows, calc(var(--dx) * #{$depth * 2}px) calc(var(--dy) * #{$depth * 2}px) 20px rgb(0 0 0 / 0.5), comma);
}
.d-lit {
--dx: 0.7;
--dy: 0.7;
display: grid;
place-items: center;
width: 100%;
height: 100%;
span {
color: #fff;
font-size: 50px;
font-weight: 900;
letter-spacing: 0.03em;
text-shadow: lit-extrude(14);
}
}