← Blurr Motion process-pinned-progress-kinetic
Categorie process Tier 1 Techniek #6 Deps gsap
00%PROCESS / KINETIC
01 / DROP

BRIEF.

Drop the deck. Voice memo, 2 min, ship it.

02 / FRAME

SCOPE.

One sentence. One screen. One week.

03 / RUN

BUILD.

Code-first. Mocks are a tax.

04 / FIRE

SHIP.

Push live. Iterate in public.

1. Mechanisme — kopieer 1-op-1, geen styling-keuzes
// Mechanisme: process-pinned-progress-kinetic
import gsap from 'https://esm.sh/[email protected]';
import { ScrollTrigger } from 'https://esm.sh/[email protected]/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const steps = gsap.utils.toArray('.kn-step');
const bar = document.querySelector('.kn-bar-fill');
const counter = document.querySelector('.kn-pct');
if (reduce) {
  gsap.set(steps, { autoAlpha: 1, y: 0 });
  if (bar) gsap.set(bar, { scaleX: 1 });
} else {
  gsap.set(steps, { autoAlpha: 0, y: 40 });
  gsap.set(steps[0], { autoAlpha: 1, y: 0 });
  ScrollTrigger.create({
    trigger: '.kn-pin', start: 'top top', end: '+=2200', pin: true, scrub: 0.4,
    onUpdate: (self) => {
      const p = self.progress;
      if (bar) gsap.set(bar, { scaleX: p });
      if (counter) counter.textContent = String(Math.round(p * 100)).padStart(2,'0') + '%';
      const idx = Math.min(steps.length - 1, Math.floor(p * steps.length));
      steps.forEach((s, i) => {
        gsap.to(s, { autoAlpha: i === idx ? 1 : 0.15, y: i === idx ? 0 : 30, duration: 0.6, ease: 'power4.out' });
      });
    }
  });
}
2. Skeleton — DOM + class-namen, mag herschikken
<!-- Skeleton: process-pinned-progress-kinetic -->
<section class="kn-pin">
  <div class="kn-bar"><div class="kn-bar-fill"></div></div>
  <div class="kn-meta"><span class="kn-pct">00%</span><span>PROCESS / KINETIC</span></div>
  <div class="kn-stage">
    <div class="kn-step"><span class="kn-tag">01 / DROP</span><h2>BRIEF.</h2><p>Drop the deck. Voice memo, 2 min, ship it.</p></div>
    <div class="kn-step"><span class="kn-tag">02 / FRAME</span><h2>SCOPE.</h2><p>One sentence. One screen. One week.</p></div>
    <div class="kn-step"><span class="kn-tag">03 / RUN</span><h2>BUILD.</h2><p>Code-first. Mocks are a tax.</p></div>
    <div class="kn-step"><span class="kn-tag">04 / FIRE</span><h2>SHIP.</h2><p>Push live. Iterate in public.</p></div>
  </div>
</section>
3. Styling-template — verplicht eigen invulling per merk
/* Styling: process-pinned-progress-kinetic — kinetic */
.kn-pin { position:relative; background:#0A0A0A; color:#fff; min-height:100vh; padding:6rem 6vw 4rem; font-family:'Archivo',sans-serif; overflow:hidden; }
.kn-bar { position:absolute; top:0; left:0; right:0; height:6px; background:rgba(255,255,255,.08); }
.kn-bar-fill { height:100%; background:#C8FF00; transform:scaleX(0); transform-origin:left center; }
.kn-meta { display:flex; justify-content:space-between; font-family:'JetBrains Mono',monospace; font-size:.78rem; letter-spacing:.16em; text-transform:uppercase; color:#C8FF00; margin-bottom:6vh; }
.kn-stage { position:relative; min-height:60vh; }
.kn-step { position:absolute; inset:0; display:flex; flex-direction:column; justify-content:center; }
.kn-tag { font-family:'JetBrains Mono',monospace; font-size:.78rem; letter-spacing:.18em; color:#FF5C3A; margin-bottom:1.2rem; }
.kn-step h2 { font-family:'Archivo Black','Archivo',sans-serif; font-weight:900; font-size:clamp(3rem,12vw,11rem); line-height:.9; letter-spacing:-.04em; margin:0 0 1.2rem; text-transform:uppercase; }
.kn-step p { font-size:clamp(1rem,1.4vw,1.3rem); max-width:36rem; color:rgba(255,255,255,.78); margin:0; }