Outline fill

Huge outlined words fill with solid colour from left to right as they pass through the screen.

How it works

The text uses background-clip: text with a hard-edged gradient: solid on the left, transparent on the right. A stroke draws the outline. Scroll progress moves the gradient’s edge by changing background-size.

Full file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Outline fill</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }

body { background: #111827; }
.list { padding: 45vh 6vw; }
.fill {
  --p: 0; margin: 0 0 6vh;
  font: 900 clamp(4rem, 17vw, 12rem)/1 system-ui, sans-serif; letter-spacing: -.04em;
  color: transparent; -webkit-text-stroke: 2px #f9a8d4;
  background: linear-gradient(90deg, #f9a8d4 0 100%) no-repeat;
  background-size: calc(var(--p) * 100%) 100%;
  -webkit-background-clip: text; background-clip: text;
}
</style>
</head>
<body>
<main class="list">
  <h2 class="fill">Design</h2>
  <h2 class="fill">Motion</h2>
  <h2 class="fill">Scroll</h2>
  <h2 class="fill">Repeat</h2>
</main>
<script>
const heads = document.querySelectorAll('.fill');
function update() {
  const vh = innerHeight;
  heads.forEach(h => {
    const r = h.getBoundingClientRect();
    const p = Math.min(1, Math.max(0, (vh * 0.85 - r.top) / (vh * 0.5)));
    h.style.setProperty('--p', p.toFixed(3));
  });
}
addEventListener('scroll', update, { passive: true });
update();
</script>
</body>
</html>

More text effects