Hero-beeld groeit tot volledig beeld New
The hero image sits as an inset below the headline and grows to full bleed while scrolling; the radius disappears and the caption fades in. Built with position: sticky and a CSS scroll-timeline driving one @property value (0 to 1); without scroll-timeline a tiny scroll listener sets the same value. With prefers-reduced-motion the image stays still.
[ Aanbouw · Amersfoort ]
Ruimte erbij,
in zes weken gebouwd.

Familie Bakker, Amersfoort18 m² · stalen pui · opgeleverd mei 2026
[ 01 ] Werkwijze
Daarna loopt de pagina gewoon door: werkwijze, prijzen en projecten.
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.
<!-- Hero-beeld groeit tot volledig beeld · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="hmg"><div class="hmg__sc" tabindex="0" aria-label="Voorbeeld: aanbouw-hero, scroll om het beeld te laten groeien"><div class="hmg__track"><div class="hmg__pin">
<p class="hmg__k">[ Aanbouw · Amersfoort ]</p>
<h4 class="hmg__t">Ruimte erbij,<br>in zes weken gebouwd.</h4>
<div class="hmg__m"><img src="https://neddev.com/lab-media/hero-media-groeit-1.webp" alt="Nieuwe aanbouw met stalen pui aan een bakstenen rijtjeshuis" loading="lazy"><p class="hmg__cap"><b>Familie Bakker, Amersfoort</b><span>18 m² · stalen pui · opgeleverd mei 2026</span></p></div>
</div></div>
<div class="hmg__na"><p class="hmg__nk">[ 01 ] Werkwijze</p><p>Daarna loopt de pagina gewoon door: werkwijze, prijzen en projecten.</p></div>
</div></div>
</div>/* Hero-beeld groeit tot volledig beeld · NedDev · eigen werk. */
@property --hmg-p{syntax:'<number>';inherits:true;initial-value:0}
.hmg{position:absolute;inset:0;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',system-ui,sans-serif;container-type:size}
.hmg__sc{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scroll-timeline:--hmg-tl y}
.hmg__sc:focus-visible{outline:2px solid #F5480F;outline-offset:-2px}
.hmg__track{height:250cqh;position:relative}
.hmg__pin{position:sticky;top:0;height:100cqh;overflow:hidden;--hmg-p:0}
@supports (animation-timeline: scroll()){.hmg__pin{animation:hmg-groei linear both;animation-timeline:--hmg-tl;animation-range:0% 62%}}
@keyframes hmg-groei{to{--hmg-p:1}}
.hmg__k{position:absolute;left:14px;top:12px;margin:0;font:500 10px 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase;color:#555;opacity:calc(1 - var(--hmg-p)*2)}
.hmg__t{position:absolute;left:14px;top:28px;margin:0;font:700 clamp(17px,6.2cqi,40px)/1.04 'Switzer',sans-serif;letter-spacing:-.03em;opacity:calc(1 - var(--hmg-p)*2.2);transform:translateY(calc(var(--hmg-p)*-24px))}
.hmg__m{position:absolute;left:50%;bottom:calc((1 - var(--hmg-p))*8cqh);width:calc(44% + 56%*var(--hmg-p));height:calc(46% + 54%*var(--hmg-p) - (1 - var(--hmg-p))*8cqh);transform:translateX(-50%);border-radius:calc((1 - var(--hmg-p))*8px);overflow:hidden;background:#cfc9c0}
.hmg__m img{display:block;width:100%;height:100%;object-fit:cover}
.hmg__cap{position:absolute;left:14px;bottom:12px;margin:0;color:#fff;display:flex;flex-direction:column;gap:2px;opacity:calc((var(--hmg-p) - .7)*3.4);text-shadow:0 1px 10px rgba(0,0,0,.45)}
.hmg__cap b{font:700 clamp(13px,4cqi,22px)/1.1 'Switzer',sans-serif;letter-spacing:-.01em}
.hmg__cap span{font:500 10px 'JetBrains Mono',monospace;letter-spacing:.04em}
.hmg__na{padding:16px 14px 30px;font-size:13px;line-height:1.5}
.hmg__na p{margin:0 0 4px}
.hmg__nk{font:600 10.5px 'JetBrains Mono',monospace;color:#b8330a;letter-spacing:.06em}
@media (prefers-reduced-motion: reduce){.hmg__pin{animation:none!important}.hmg__track{height:auto}.hmg__pin{position:relative}}// Hero-beeld groeit tot volledig beeld · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.hmg')||root;function lab_drift(sc,host,speed){if(matchMedia('(prefers-reduced-motion: reduce)').matches)return;var on=true,t0=0;function stop(){on=false;}
['wheel','touchstart','pointerdown','keydown','focusin'].forEach(function(ev){host.addEventListener(ev,stop,{passive:true});});
function f(now){if(!on)return;if(!t0)t0=now;var max=sc.scrollHeight-sc.clientHeight,ph=(now-t0)/1000*speed;sc.scrollTop=max*(.5-.5*Math.cos(ph));requestAnimationFrame(f);}
setTimeout(function(){if(on)requestAnimationFrame(f);},900);}
var sc=root.querySelector('.hmg__sc'),pin=root.querySelector('.hmg__pin');
var rm=matchMedia('(prefers-reduced-motion: reduce)').matches;
if(!rm&&!(window.CSS&&CSS.supports&&CSS.supports('animation-timeline: scroll()'))){var tick=false;
function upd(){tick=false;var max=sc.scrollHeight-sc.clientHeight;var p=max>0?Math.min(1,sc.scrollTop/(max*.62)):0;pin.style.setProperty('--hmg-p',p.toFixed(4));}
sc.addEventListener('scroll',function(){if(!tick){tick=true;requestAnimationFrame(upd);}},{passive:true});upd();}
if(!rm)lab_drift(sc,root,.32);
}
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 →