Inzoomen door een reeks foto's Nieuw
In elke foto zit de volgende als klein ingelijst beeld; scrollen zoomt erin tot dat beeld het hele vak vult, en zo verder: van Utrecht naar de gracht, de gevel, de bar en het kopje koffie (Droste-effect). Onderin staat waar je bent. Voor een "zo vind je ons" of de hero van een horecazaak of winkel. Eigen scrollvak met toetsenbord; bij minder beweging wisselen de foto's met een overvloeier in plaats van een zoom.





Utrecht Midden in de binnenstad, vijf minuten van het station.
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.
<!-- Inzoomen door een reeks foto's · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="dz">
<div class="dz__vak" tabindex="0" role="region" aria-label="Van Utrecht naar een kopje koffie in vijf foto's. Scroll in dit vak om in te zoomen.">
<div class="dz__baan">
<div class="dz__beeld">
<div class="dz__laag"><img src="https://neddev.com/lab-media/r7scr-droste-1.webp" alt="Utrecht van boven met de Domtoren en de grachten" width="1000" height="622"></div>
<div class="dz__laag"><img src="https://neddev.com/lab-media/r7scr-droste-2.webp" alt="De Oudegracht met werfkelders aan het water" width="1000" height="622"></div>
<div class="dz__laag"><img src="https://neddev.com/lab-media/r7scr-droste-3.webp" alt="Gevel van de koffiebar in een grachtenpand" width="1000" height="622"></div>
<div class="dz__laag"><img src="https://neddev.com/lab-media/r7scr-droste-4.webp" alt="De bar met espressomachine" width="1000" height="622"></div>
<div class="dz__laag"><img src="https://neddev.com/lab-media/r7scr-droste-5.webp" alt="Een flat white met latte art van boven" width="1000" height="622"></div>
<p class="dz__plek" aria-live="polite"><strong>Utrecht</strong> <span>Midden in de binnenstad, vijf minuten van het station.</span></p>
</div>
</div>
</div>
<p class="dz__hint" aria-hidden="true">Scroll om in te zoomen</p>
</div>
</div>/* Inzoomen door een reeks foto's · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.dz{position:absolute;inset:0;container-type:size;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;background:#0a0a0a}
.dz__vak{position:absolute;inset:0;overflow-y:auto;scrollbar-width:none}
.dz__vak::-webkit-scrollbar{display:none}
.dz__vak:focus-visible{outline:2px solid #F5480F;outline-offset:-2px}
.dz__baan{height:700cqh}
.dz__beeld{position:sticky;top:0;height:100cqh;overflow:hidden}
.dz__laag{position:absolute;left:0;top:0;width:100%;height:100%;transform-origin:0 0;visibility:hidden;will-change:transform}
.dz__laag img{width:100%;height:100%;object-fit:cover;display:block}
.dz__plek{position:absolute;left:10px;bottom:10px;right:10px;max-width:220px;margin:0;font-size:12px;line-height:1.35;background:#fff;padding:6px 9px;border-radius:4px;z-index:9}
.dz__plek strong{display:block;font-size:15px}
.dz__hint{position:absolute;right:10px;top:10px;margin:0;font-size:12px;background:#fff;padding:3px 8px;border-radius:4px;pointer-events:none;transition:opacity .3s;z-index:9}
.dz.is-weg .dz__hint{opacity:0}// Inzoomen door een reeks foto's · © 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('.dz'); if (!w) return;
const vak = w.querySelector('.dz__vak'), beeld = w.querySelector('.dz__beeld'), lagen = [...w.querySelectorAll('.dz__laag')], plek = w.querySelector('.dz__plek');
const rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
const S = 3.4, n = lagen.length;
const A = [[.68, .6], [.8, .58], [.42, .6], [.64, .64]];
const T = [['Utrecht', 'Midden in de binnenstad, vijf minuten van het station.'], ['Oudegracht', 'Aan de werf, waar de kelders aan het water liggen.'], ['Koffiebar Werfkelder', 'Oudegracht 112, elke dag open vanaf 08:00.'], ['Aan de bar', 'Bonen van een kleine branderij uit Amersfoort.'], ['Jouw flat white', '€ 3,90, havermelk zonder meerprijs.']];
lagen.forEach((l, j) => { l.style.zIndex = j + 1; });
let raf = 0, nu = 0;
function zet(l, sc, tx, ty, W, H, rand) {
l.style.visibility = 'visible';
l.style.transform = 'translate(' + (tx * W).toFixed(2) + 'px,' + (ty * H).toFixed(2) + 'px) scale(' + sc.toFixed(5) + ')';
l.style.outline = rand > .01 ? (rand / sc).toFixed(2) + 'px solid #fff' : 'none';
}
function teken() {
raf = 0; const m = vak.scrollHeight - vak.clientHeight, p = m > 0 ? vak.scrollTop / m : 0;
const W = beeld.clientWidth, H = beeld.clientHeight, z = p * (n - 1);
if (rm) {
lagen.forEach((l, j) => { l.style.visibility = 'visible'; l.style.transform = 'none'; l.style.outline = 'none'; l.style.opacity = Math.max(0, Math.min(1, (z - j + .5) * 2)); });
lagen[0].style.opacity = 1;
} else {
const k = Math.min(Math.floor(z), n - 2), f = z - k, s = Math.pow(S, f), h = (s - 1) / (S - 1);
const a = A[k], cx = a[0] + (.5 - a[0]) * h, cy = a[1] + (.5 - a[1]) * h;
lagen.forEach(l => { l.style.visibility = 'hidden'; });
zet(lagen[k], s, cx - s * a[0], cy - s * a[1], W, H, 0);
zet(lagen[k + 1], s / S, cx - s / S * .5, cy - s / S * .5, W, H, 3 * (1 - f));
if (k + 2 < n) { const b = A[k + 1]; zet(lagen[k + 2], s / S / S, cx + s / S * (b[0] - .5) - s / S / S * .5, cy + s / S * (b[1] - .5) - s / S / S * .5, W, H, 2); }
}
const i = Math.min(n - 1, Math.round(z));
if (i !== nu) { nu = i; plek.innerHTML = '<strong>' + T[i][0] + '</strong> <span>' + T[i][1] + '</span>'; }
w.classList.toggle('is-weg', vak.scrollTop > 8);
}
vak.addEventListener('scroll', () => { if (!raf) raf = requestAnimationFrame(teken); }, { passive: true });
if (window.ResizeObserver) new ResizeObserver(() => teken()).observe(beeld);
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 →