Huis bouwt zich op tijdens scrollen New
A house appears layer by layer as you scroll inside the box: foundation, walls row by row, frames, roof and solar panels, with the build week and phase alongside. For a "how we build" page or the hero of a contractor. Own scroll box, keyboard works (focus the box, arrow keys); with reduced motion parts fade in instead of dropping.
Uw huis in 16 weken
FunderingWeek 1 tot 3: heipalen en een betonnen fundering.
Week 1 van 16
How to use it
- Paste the HTML where the scroll effects should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Huis bouwt zich op tijdens scrollen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="hb">
<div class="hb__vak" tabindex="0" role="region" aria-label="Bouw van een huis in vijf fases. Scroll in dit vak om het huis op te bouwen.">
<div class="hb__baan">
<div class="hb__beeld">
<div class="hb__tekst">
<h3 class="hb__kop">Uw huis in 16 weken</h3>
<p class="hb__fase" aria-live="polite"><strong class="hb__naam">Fundering</strong><span class="hb__uitleg">Week 1 tot 3: heipalen en een betonnen fundering.</span></p>
<div class="hb__balk" aria-hidden="true"><i></i></div>
<p class="hb__week">Week 1 van 16</p>
</div>
<svg class="hb__svg" viewBox="0 0 240 200" role="img" aria-label="Tekening van het huis in aanbouw">
<defs>
<pattern id="hb-steen-a" width="16" height="9" patternUnits="userSpaceOnUse"><rect width="16" height="9" fill="#c2603a"/><path d="M0 8.5H16M15.5 0V9" stroke="#f4f3f1" stroke-width="1" opacity=".55"/></pattern>
<pattern id="hb-steen-b" width="16" height="9" patternUnits="userSpaceOnUse" x="8"><rect width="16" height="9" fill="#b9572f"/><path d="M0 8.5H16M15.5 0V9" stroke="#f4f3f1" stroke-width="1" opacity=".55"/></pattern>
</defs>
<path class="hb__spook" d="M44 158V95H196V158M34 96L120 42L206 96Z" fill="none" stroke="#0a0a0a" stroke-opacity=".25" stroke-dasharray="3 3"/>
<rect x="0" y="168" width="240" height="32" fill="#e3dfd9"/>
<g data-l="0"><rect x="54" y="168" width="6" height="26" fill="#6d6964"/><rect x="94" y="168" width="6" height="26" fill="#6d6964"/><rect x="140" y="168" width="6" height="26" fill="#6d6964"/><rect x="180" y="168" width="6" height="26" fill="#6d6964"/><rect x="40" y="158" width="160" height="12" fill="#8d8882"/></g>
<g class="hb__muur"></g>
<g data-l="4"><rect x="160" y="50" width="13" height="30" fill="#a9532f"/></g>
<g data-l="3"><path d="M34 96L120 42L206 96Z" fill="#1c1c1c"/><path d="M52 85H188M70 74H170M88 63H152" stroke="#3a3a3a" stroke-width="1.5"/></g>
<g data-l="2"><rect x="58" y="108" width="40" height="30" fill="#dce8ee" stroke="#fff" stroke-width="3"/><path d="M78 108V138M58 123H98" stroke="#fff" stroke-width="2"/><rect x="142" y="108" width="40" height="30" fill="#dce8ee" stroke="#fff" stroke-width="3"/><path d="M162 108V138M142 123H182" stroke="#fff" stroke-width="2"/><rect x="106" y="122" width="28" height="36" fill="#F5480F" stroke="#fff" stroke-width="3"/><circle cx="128" cy="141" r="1.8" fill="#0a0a0a"/></g>
<g data-l="4"><path d="M58 81L96 57L103 69L65 93Z" fill="#2b3440" stroke="#fff" stroke-width=".8"/><path d="M77 69L84 81M62 87L99 63" stroke="#fff" stroke-width=".6"/><circle cx="52" cy="160" r="8" fill="#6f8f4e"/><circle cx="190" cy="160" r="7" fill="#7fa05a"/></g>
</svg>
</div>
</div>
</div>
<p class="hb__hint" aria-hidden="true">Scroll om te bouwen <svg viewBox="0 0 12 12"><path d="M6 2v8M2.5 6.5 6 10l3.5-3.5" fill="none" stroke="currentColor" stroke-width="1.6"/></svg></p>
</div>
</div>/* Huis bouwt zich op tijdens scrollen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.hb{position:absolute;inset:0;container-type:size;background:#f4f3f1;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a}
.hb__vak{position:absolute;inset:0;overflow-y:auto;scrollbar-width:none}
.hb__vak::-webkit-scrollbar{display:none}
.hb__vak:focus-visible{outline:2px solid #F5480F;outline-offset:-2px}
.hb__baan{height:500cqh}
.hb__beeld{position:sticky;top:0;height:100cqh;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);align-items:center;gap:8px;padding:0 12px 0 16px;box-sizing:border-box}
.hb__kop{font-size:clamp(15px,4.6cqw,20px);font-weight:700;line-height:1.15;margin:0 0 10px}
.hb__fase{margin:0}
.hb__naam{display:block;font-size:clamp(13px,3.6cqw,16px);font-weight:600;color:#b83a0b}
.hb__uitleg{display:block;font-size:12px;line-height:1.4;color:#3d3d3d;margin-top:2px}
.hb__balk{height:4px;background:rgba(10,10,10,.12);border-radius:4px;margin:12px 0 6px;overflow:hidden}
.hb__balk i{display:block;height:100%;background:#F5480F;transform-origin:left;transform:scaleX(0)}
.hb__week{font-size:12px;margin:0;color:#3d3d3d;font-variant-numeric:tabular-nums}
.hb__svg{width:100%;height:auto;max-height:92cqh;display:block}
.hb__hint{position:absolute;right:10px;bottom:8px;margin:0;display:flex;align-items:center;gap:4px;font-size:12px;background:#fff;padding:3px 8px;border-radius:4px;pointer-events:none;transition:opacity .3s}
.hb__hint svg{width:12px;height:12px}
.hb.is-weg .hb__hint{opacity:0}
@media (prefers-reduced-motion:reduce){.hb__hint{transition:none}}// Huis bouwt zich op tijdens scrollen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie
// root = het element waarin de HTML staat
function init(root){
const w = root.querySelector('.hb'); if (!w) return;
const vak = w.querySelector('.hb__vak'), svg = w.querySelector('.hb__svg');
const naam = w.querySelector('.hb__naam'), uitleg = w.querySelector('.hb__uitleg'), balk = w.querySelector('.hb__balk i'), week = w.querySelector('.hb__week');
const rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
const NS = 'http://www.w3.org/2000/svg', muur = svg.querySelector('.hb__muur'), rijen = [];
for (let k = 0; k < 7; k++) {
const r = document.createElementNS(NS, 'rect');
r.setAttribute('x', 44); r.setAttribute('y', 149 - 9 * k); r.setAttribute('width', 152); r.setAttribute('height', 9);
r.setAttribute('fill', k % 2 ? 'url(#hb-steen-b)' : 'url(#hb-steen-a)'); muur.appendChild(r); rijen.push(r);
}
const lagen = [...svg.querySelectorAll('[data-l]')];
const fases = [[0, .16, 'Fundering', 'Week 1 tot 3: heipalen en een betonnen fundering.'], [.16, .46, 'Muren', 'Week 4 tot 9: metselwerk, laag voor laag.'], [.46, .62, 'Kozijnen', 'Week 10 tot 12: kozijnen, glas en de voordeur.'], [.62, .8, 'Dak', 'Week 13 tot 15: dakplaten, isolatie en pannen.'], [.8, .96, 'Oplevering', 'Week 16: zonnepanelen erop en de sleutel naar u.']];
const cl = v => v < 0 ? 0 : v > 1 ? 1 : v, ease = t => 1 - Math.pow(1 - t, 3);
const zet = (el, t, dy) => { el.style.opacity = t; el.style.transform = rm ? '' : 'translateY(' + (-(1 - ease(t)) * dy).toFixed(2) + 'px)'; };
let laatste = -1, raf = 0;
function teken() {
raf = 0; const m = vak.scrollHeight - vak.clientHeight, p = m > 0 ? vak.scrollTop / m : 0;
lagen.forEach(g => { const f = fases[+g.dataset.l]; zet(g, cl((p - f[0]) / (f[1] - f[0])), g.dataset.l === '3' ? 40 : 18); });
const fm = fases[1], stap = (fm[1] - fm[0]) / 7;
rijen.forEach((r, k) => zet(r, cl((p - fm[0] - stap * k) / stap), 14));
let i = 0; fases.forEach((f, j) => { if (p >= f[0]) i = j; });
if (i !== laatste) { laatste = i; naam.textContent = fases[i][2]; uitleg.textContent = fases[i][3]; }
balk.style.transform = 'scaleX(' + p.toFixed(3) + ')';
week.textContent = 'Week ' + (1 + Math.round(p * 15)) + ' van 16';
w.classList.toggle('is-weg', vak.scrollTop > 8);
}
vak.addEventListener('scroll', () => { if (!raf) raf = requestAnimationFrame(teken); }, { passive: true });
teken();
}
init(document.querySelector('.jouw-container'));
More scroll effects
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →