Video-modal met facade New
Company video as a facade: poster, title, duration and play button, with no YouTube script or cookies until someone clicks. Clicking opens a
Laadt pas na klik · geen cookies vooraf
How to use it
- Paste the HTML where the components 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.
<!-- Video-modal met facade · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="vdm">
<button class="vdm__facade" type="button" aria-haspopup="dialog" aria-label="Speel bedrijfsfilm af: van plank tot keuken, 1 minuut 42">
<img src="https://neddev.com/lab-media/video-modal-1.webp" alt="" width="1000" height="545" loading="lazy">
<span class="vdm__shade" aria-hidden="true"></span>
<span class="vdm__meta" aria-hidden="true"><span class="vdm__tag">Bedrijfsfilm · 1:42</span><span class="vdm__title">Van plank tot keuken: een week in onze werkplaats in Apeldoorn</span></span>
<span class="vdm__play" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg></span>
</button>
<p class="vdm__note">Laadt pas na klik · geen cookies vooraf</p>
<dialog class="vdm__dlg" aria-label="Bedrijfsfilm: van plank tot keuken">
<div class="vdm__frame">
<div class="vdm__film" aria-hidden="true"><span class="vdm__wood"></span><span class="vdm__beam"></span><span class="vdm__demo">Voorbeeldbeeld · hier komt je video</span></div>
<p class="vdm__sub"></p>
<div class="vdm__load" role="status"><span class="vdm__spin" aria-hidden="true"></span><span>Video laden</span></div>
<div class="vdm__ctrl">
<button class="vdm__pp" type="button" aria-label="Pauzeer video"><svg class="vdm__i-pause" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6v12M15 6v12"/></svg><svg class="vdm__i-play" viewBox="0 0 24 24" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></button>
<span class="vdm__time">0:00 / 1:42</span>
<span class="vdm__track" role="progressbar" aria-label="Afgespeeld" aria-valuemin="0" aria-valuemax="102" aria-valuenow="0" aria-valuetext="0 seconden van 1 minuut 42"><span class="vdm__tfill"></span></span>
<button class="vdm__mute" type="button" aria-pressed="false" aria-label="Geluid uit"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 9v6h4l5 4V5L8 9z"/><path class="vdm__wave" d="M16.5 8.5a5 5 0 0 1 0 7"/><path class="vdm__xm" d="M16 9.5l5 5M21 9.5l-5 5"/></svg></button>
</div>
<button class="vdm__x" type="button" aria-label="Sluit video"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button>
</div>
</dialog>
</div>
</div>/* Video-modal met facade · NedDev · eigen werk. */
.vdm{--pop:#F5480F;--pd:#b83a0b;position:absolute;inset:0;font-family:'Switzer',system-ui,sans-serif;color:#fff;background:#0a0a0a;overflow:hidden}
.vdm__facade{position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;background:#1b1b1b;cursor:pointer;color:#fff;text-align:left;display:block}
.vdm__facade img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .5s cubic-bezier(.2,.7,.2,1)}
.vdm__facade:hover img{transform:scale(1.03)}
.vdm__shade{position:absolute;inset:0;background:linear-gradient(90deg,rgba(10,10,10,.82) 0%,rgba(10,10,10,.35) 60%,rgba(10,10,10,.1))}
.vdm__meta{position:absolute;left:18px;bottom:18px;right:90px;display:flex;flex-direction:column;gap:6px}
.vdm__tag{font:600 10px/1 'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:#ffd9c9}
.vdm__title{font-size:17px;font-weight:600;line-height:1.25;max-width:24ch}
.vdm__play{position:absolute;right:18px;bottom:18px;width:56px;height:56px;border-radius:50%;background:var(--pop);display:grid;place-items:center;transition:transform .2s ease,background .2s}
.vdm__play svg{width:22px;height:22px;fill:#0a0a0a;margin-left:3px}
.vdm__facade:hover .vdm__play{transform:scale(1.06);background:#ff6a35}
.vdm__facade:active .vdm__play{transform:scale(.97)}
.vdm__facade:focus-visible{outline:3px solid var(--pop);outline-offset:-3px}
.vdm__note{position:absolute;top:12px;left:18px;margin:0;font:600 9.5px/1 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.82);pointer-events:none}
.vdm__dlg{position:absolute;inset:0;margin:0;width:100%;height:100%;max-width:none;max-height:none;border:0;padding:0;background:#000;color:#fff;display:grid;place-items:center;opacity:0;transform:scale(.97);transition:opacity .22s ease,transform .22s ease,display .22s allow-discrete,overlay .22s allow-discrete}
.vdm__dlg:not([open]){display:none}
.vdm__dlg[open]{opacity:1;transform:none}
@starting-style{.vdm__dlg[open]{opacity:0;transform:scale(.97)}}
.vdm__frame{position:relative;width:100%;max-height:100%;aspect-ratio:16/9;overflow:hidden;background:#140d08}
.vdm__film{position:absolute;inset:0;overflow:hidden}
.vdm__wood{position:absolute;inset:-20%;background:repeating-linear-gradient(100deg,#6b4423 0 14px,#7a4f2a 14px 22px,#5e3b1e 22px 40px,#83582f 40px 46px);filter:saturate(.9);animation:vdm-pan 14s linear infinite alternate}
.vdm__beam{position:absolute;inset:0;background:radial-gradient(60% 80% at 30% 20%,rgba(255,214,160,.55),rgba(255,214,160,0) 70%),linear-gradient(rgba(0,0,0,0) 55%,rgba(0,0,0,.6));animation:vdm-beam 9s ease-in-out infinite alternate}
.vdm__demo{position:absolute;top:10px;left:12px;font:600 9px/1 'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.75);background:rgba(0,0,0,.35);padding:4px 6px;border-radius:2px}
@keyframes vdm-pan{to{transform:translate(8%,-4%) rotate(2deg)}}
@keyframes vdm-beam{to{transform:translateX(18%)}}
.vdm.is-paused .vdm__wood,.vdm.is-paused .vdm__beam,.vdm.is-loading .vdm__wood,.vdm.is-loading .vdm__beam{animation-play-state:paused}
.vdm__sub{position:absolute;left:50%;bottom:48px;transform:translateX(-50%);margin:0;width:max-content;max-width:86%;text-align:center;font-size:13px;line-height:1.35;background:rgba(0,0,0,.65);padding:4px 8px;border-radius:2px}
.vdm__sub:empty{display:none}
.vdm__load{position:absolute;inset:0;display:none;align-items:center;justify-content:center;gap:10px;background:rgba(0,0,0,.55);font-size:13px}
.vdm.is-loading .vdm__load{display:flex}
.vdm__spin{width:20px;height:20px;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;border-radius:50%;animation:vdm-spin .8s linear infinite}
@keyframes vdm-spin{to{transform:rotate(360deg)}}
.vdm__ctrl{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:10px;padding:8px 10px;background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.75))}
.vdm__ctrl button,.vdm__x{width:30px;height:30px;border:0;border-radius:4px;background:rgba(255,255,255,.08);color:#fff;cursor:pointer;display:grid;place-items:center;padding:0;flex:none;transition:background .15s}
.vdm__ctrl button:hover,.vdm__x:hover{background:rgba(255,255,255,.2)}
.vdm__dlg button:focus-visible{outline:2px solid var(--pop);outline-offset:2px}
.vdm__ctrl svg,.vdm__x svg{width:15px;height:15px;fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.vdm__i-play{fill:#fff!important;stroke:none!important;display:none}
.vdm.is-paused .vdm__i-play{display:block}.vdm.is-paused .vdm__i-pause{display:none}
.vdm__xm{display:none}.vdm.is-muted .vdm__xm{display:inline}.vdm.is-muted .vdm__wave{display:none}
.vdm__time{font:600 11px/1 'JetBrains Mono',monospace;font-variant-numeric:tabular-nums;white-space:nowrap}
.vdm__track{flex:1;height:3px;background:rgba(255,255,255,.25);border-radius:2px;overflow:hidden}
.vdm__tfill{display:block;height:100%;width:0;background:var(--pop)}
.vdm__x{position:absolute;top:8px;right:8px;background:rgba(0,0,0,.5)}
@media (max-width:420px){.vdm__title{font-size:14.5px}.vdm__meta{left:14px;bottom:14px;right:80px}.vdm__play{width:48px;height:48px;right:14px;bottom:14px}.vdm__sub{font-size:11.5px;bottom:44px}.vdm__time{font-size:10px}}
@media (prefers-reduced-motion:reduce){.vdm__wood,.vdm__beam{animation:none}.vdm__dlg,.vdm__facade img{transition:none}}// Video-modal met facade · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.vdm');if(!w)return;
var fac=w.querySelector('.vdm__facade'),dlg=w.querySelector('.vdm__dlg'),pp=w.querySelector('.vdm__pp'),mute=w.querySelector('.vdm__mute'),sub=w.querySelector('.vdm__sub'),tm=w.querySelector('.vdm__time'),trk=w.querySelector('.vdm__track'),fill=w.querySelector('.vdm__tfill');
var LEN=102,t=0,tick=0,loadT=0,playing=false;
var SUBS=['Elke keuken begint bij ons als ruwe eikenhouten plank.','In de werkplaats in Apeldoorn zagen en schaven we alles op maat.','Na een week staat hij bij jou thuis, gemonteerd en schoon opgeleverd.'];
function fmt(s){s=Math.floor(s);return Math.floor(s/60)+':'+(s%60<10?'0':'')+(s%60);}
function draw(){tm.textContent=fmt(t)+' / '+fmt(LEN);fill.style.width=(t/LEN*100)+'%';trk.setAttribute('aria-valuenow',Math.floor(t));trk.setAttribute('aria-valuetext',fmt(t)+' van 1:42');sub.textContent=SUBS[Math.floor(t/5)%SUBS.length];}
function setPlay(on){playing=on;w.classList.toggle('is-paused',!on);pp.setAttribute('aria-label',on?'Pauzeer video':'Speel video af');clearInterval(tick);if(on)tick=setInterval(function(){t=(t+1)%LEN;draw();},1000);}
function open(){
// Productie: maak hier pas de iframe aan, bv. frame.innerHTML='<iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID?autoplay=1" title="Bedrijfsfilm" allow="autoplay; fullscreen" allowfullscreen></iframe>'
dlg.show();fac.inert=true;w.classList.add('is-loading');sub.textContent='';t=0;draw();sub.textContent='';pp.focus();
loadT=setTimeout(function(){w.classList.remove('is-loading');setPlay(true);draw();},700);}
function close(){clearTimeout(loadT);setPlay(false);w.classList.remove('is-loading','is-paused');dlg.close();fac.inert=false;fac.focus();}
fac.addEventListener('click',open);
w.querySelector('.vdm__x').addEventListener('click',close);
pp.addEventListener('click',function(){if(w.classList.contains('is-loading'))return;setPlay(!playing);});
mute.addEventListener('click',function(){var m=!w.classList.contains('is-muted');w.classList.toggle('is-muted',m);mute.setAttribute('aria-pressed',m);});
dlg.addEventListener('click',function(e){if(e.target===dlg)close();});
dlg.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();close();return;}
if(e.key===' '&&e.target===dlg){e.preventDefault();pp.click();}
if(e.key==='Tab'){var f=[pp,mute,w.querySelector('.vdm__x')],a=f[0],z=f[f.length-1];if(e.shiftKey&&document.activeElement===a){e.preventDefault();z.focus();}else if(!e.shiftKey&&document.activeElement===z){e.preventDefault();a.focus();}}});
dlg.addEventListener('cancel',function(e){e.preventDefault();close();});
}
init(document.querySelector('.jouw-container'));
More components
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 →