Huis bouwt zich op tijdens scrollen Nieuw
Een huis verschijnt laag voor laag terwijl je in het vak scrolt: fundering, muren rij voor rij, kozijnen, dak en zonnepanelen, met de bouwweek en de fase ernaast. Voor de pagina "zo bouwen wij" of de hero van een aannemer of bouwbedrijf. Eigen scrollvak, toetsenbord werkt (focus het vak, pijltjes), bij minder beweging vallen de delen niet in maar verschijnen ze.
Uw huis in 16 weken
FunderingWeek 1 tot 3: heipalen en een betonnen fundering.
Week 1 van 16
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- 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'));
Meer uit scroll-effecten
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →