Envelop opent en de uitnodiging schuift eruit New
A sealed envelope: scrolling flips the flap open, the invitation slides out and comes forward, with a button that gives a calendar file (.ics). For the thank-you page after a sign-up, an open day invitation or an anniversary party. Own scroll box with keyboard support; the button is only reachable once the letter is out, and with reduced motion the flap fades instead of flipping.
Welkom op onze open dag
Zaterdag 14 november, 10:00 tot 13:00
De Vlinder, Kerkstraat 8, Amersfoort
Rondleiding om 10:30 en 11:30. Kinderen zijn welkom, aanmelden hoeft niet.
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.
<!-- Envelop opent en de uitnodiging schuift eruit · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="ev">
<div class="ev__vak" tabindex="0" role="region" aria-label="Uitnodiging voor de open dag. Scroll in dit vak om de envelop te openen.">
<div class="ev__baan">
<div class="ev__beeld">
<div class="ev__env">
<div class="ev__achter"></div>
<div class="ev__brief" inert>
<h3 class="ev__kop">Welkom op onze open dag</h3>
<p class="ev__p">Zaterdag 14 november, 10:00 tot 13:00<br>De Vlinder, Kerkstraat 8, Amersfoort</p>
<p class="ev__p ev__p--klein">Rondleiding om 10:30 en 11:30. Kinderen zijn welkom, aanmelden hoeft niet.</p>
<button type="button" class="ev__knop">Zet in mijn agenda</button>
</div>
<div class="ev__voor"></div>
<div class="ev__klep"><span class="ev__zegel" aria-hidden="true">V</span></div>
</div>
</div>
</div>
</div>
<p class="ev__hint" aria-hidden="true">Scroll om te openen</p>
</div>
</div>/* Envelop opent en de uitnodiging schuift eruit · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.ev{position:absolute;inset:0;container-type:size;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;background:#f4f3f1}
.ev__vak{position:absolute;inset:0;overflow-y:auto;scrollbar-width:none}
.ev__vak::-webkit-scrollbar{display:none}
.ev__vak:focus-visible{outline:2px solid #F5480F;outline-offset:-2px}
.ev__baan{height:500cqh}
.ev__beeld{position:sticky;top:0;height:100cqh;overflow:hidden}
.ev__env{position:absolute;left:50%;top:0;width:min(70cqw,118cqh);aspect-ratio:1.55;perspective:600px;transform:translateX(-50%)}
.ev__achter{position:absolute;inset:0;background:#c63a0c;border-radius:4px}
.ev__brief{position:absolute;left:4%;top:6%;width:92%;height:88%;box-sizing:border-box;display:flex;flex-direction:column;align-items:flex-start;background:#fff;border-radius:4px;padding:10px 12px;overflow:hidden;z-index:2;box-shadow:0 1px 3px rgba(10,10,10,.18)}
.ev__kop{font-size:clamp(14px,4.4cqw,18px);font-weight:700;line-height:1.15;margin:0 0 6px}
.ev__p{font-size:12px;line-height:1.4;margin:0 0 8px;color:#333}
.ev__p--klein{color:#5b5b5b}
@container (max-width:380px){.ev__p--klein{display:none}}
.ev__knop{margin-top:auto;flex:none;font:600 12px 'Switzer',system-ui,sans-serif;min-height:28px;padding:5px 10px;border:0;border-radius:4px;background:#F5480F;color:#0a0a0a;cursor:pointer}
.ev__knop:hover{background:#0a0a0a;color:#fff}
.ev__knop:focus-visible{outline:2px solid #0a0a0a;outline-offset:2px}
.ev__voor{position:absolute;inset:0;z-index:3;background:#F5480F;border-radius:4px;clip-path:polygon(0 0,50% 54%,100% 0,100% 100%,0 100%)}
.ev__klep{position:absolute;left:0;top:0;width:100%;height:58%;z-index:4;transform-origin:50% 0;background:#e0400b;clip-path:polygon(0 0,100% 0,50% 100%)}
.ev__klep.is-open{z-index:1;background:#0a0a0a}
.ev__zegel{position:absolute;left:50%;bottom:6%;width:22px;height:22px;margin-left:-11px;border-radius:50%;background:#0a0a0a;color:#F5480F;font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center}
.ev__klep.is-open .ev__zegel{opacity:0}
.ev__hint{position:absolute;right:10px;top:8px;margin:0;font-size:12px;background:#fff;padding:3px 8px;border-radius:4px;pointer-events:none;transition:opacity .3s}
.ev.is-weg .ev__hint{opacity:0}// Envelop opent en de uitnodiging schuift eruit · © 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('.ev'); if (!w) return;
const vak = w.querySelector('.ev__vak'), env = w.querySelector('.ev__env'), brief = w.querySelector('.ev__brief'), klep = w.querySelector('.ev__klep'), knop = w.querySelector('.ev__knop');
const rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
const cl = v => v < 0 ? 0 : v > 1 ? 1 : v, ease = t => t < .5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
let raf = 0;
function teken() {
raf = 0; const m = vak.scrollHeight - vak.clientHeight, p = m > 0 ? vak.scrollTop / m : 0;
const H = vak.clientHeight, eH = env.offsetHeight, bH = brief.offsetHeight;
const a = ease(cl(p / .3)), b = ease(cl((p - .32) / .5));
const top0 = (H - eH) / 2, opstijg = bH + eH * .06 + 6, top1 = (H - bH) / 2 - eH * .06 + opstijg;
env.style.transform = 'translate(-50%,' + (top0 + (top1 - top0) * b).toFixed(1) + 'px)';
brief.style.transform = 'translateY(' + (-opstijg * b).toFixed(1) + 'px)';
if (rm) { klep.style.opacity = 1 - a; klep.classList.toggle('is-open', a > .5); }
else { klep.style.transform = 'rotateX(' + (a * 178).toFixed(1) + 'deg)'; klep.classList.toggle('is-open', a > .5); }
const klaar = p > .84; brief.inert = !klaar; brief.style.zIndex = b > 0 ? 5 : 2;
w.classList.toggle('is-weg', vak.scrollTop > 8);
}
knop.addEventListener('click', () => {
const ics = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//De Vlinder//Open dag//NL', 'BEGIN:VEVENT', 'UID:opendag-2026@voorbeeld.nl', 'DTSTAMP:20261020T090000Z', 'DTSTART:20261114T090000Z', 'DTEND:20261114T120000Z', 'SUMMARY:Open dag De Vlinder', 'LOCATION:Kerkstraat 8\\, Amersfoort', 'END:VEVENT', 'END:VCALENDAR'].join('\r\n');
const a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([ics], { type: 'text/calendar' })); a.download = 'open-dag-de-vlinder.ics';
document.body.appendChild(a); a.click(); a.remove(); setTimeout(() => URL.revokeObjectURL(a.href), 1000);
knop.textContent = 'Agendabestand gedownload';
});
vak.addEventListener('scroll', () => { if (!raf) raf = requestAnimationFrame(teken); }, { passive: true });
if (window.ResizeObserver) new ResizeObserver(() => teken()).observe(vak);
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 →