Video-preview bij hover New
A project card that plays a timelapse on hover; move sideways to scrub through it, with timecode and progress bar. For case studies with build footage or product demos.
Timelapse
0:00 / 0:08
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-preview bij hover · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="hvs"><div class="hvs__media" tabindex="0" role="button" aria-label="Speel timelapse af">
<div class="hvs__scene" aria-hidden="true"><span class="hvs__sky"></span><span class="hvs__sun"></span><span class="hvs__cl hvs__cl--a"></span><span class="hvs__cl hvs__cl--b"></span>
<span class="hvs__crane"><i class="hvs__mast"></i><i class="hvs__jib"><b class="hvs__cab"></b><b class="hvs__load"></b></i></span>
<span class="hvs__bld"><i style="--f:0"></i><i style="--f:1"></i><i style="--f:2"></i><i style="--f:3"></i><i style="--f:4"></i><i style="--f:5"></i></span><span class="hvs__bld2"></span><span class="hvs__gr"></span></div>
<span class="hvs__tag">Timelapse</span><span class="hvs__pl" aria-hidden="true"><svg viewBox="0 0 12 12" width="12" height="12"><path d="M3 1.5v9l7.5-4.5z" fill="currentColor"/></svg></span>
<div class="hvs__ui"><span class="hvs__tc">0:00 / 0:08</span><span class="hvs__pb"><span class="hvs__pf"></span></span></div></div>
<div class="hvs__meta"><b>Nieuwbouw 24 woningen, Ypenburg</b><span>Van Dam Bouw · 2026</span></div></div>
</div>/* Video-preview bij hover · NedDev · eigen werk. */
.hvs{position:absolute;inset:0;background:#f4f3f1;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;padding:12px;display:flex;flex-direction:column;gap:7px;container-type:inline-size}
.hvs__media{position:relative;flex:1;min-height:0;border-radius:5px;overflow:hidden;cursor:ew-resize;outline:none}
.hvs__media:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.hvs__scene,.hvs__scene span{position:absolute}
.hvs__scene{inset:0}
.hvs__sky{inset:0;background:linear-gradient(180deg,#1b2333 0%,#3f4a63 18%,#f2a27c 36%,#f7d9bf 50%,#e9eef2 64%,#f6c2a1 82%,#5b3d3a 100%);background-size:100% 520%;animation:hvs-sky 8s linear both}
.hvs__sun{width:9%;aspect-ratio:1;border-radius:50%;background:#F5480F;animation:hvs-sun 8s linear both}
.hvs__cl{height:6%;border-radius:999px;background:rgba(255,255,255,.75);animation:hvs-cl 8s linear both}
.hvs__cl--a{width:22%;top:14%;left:4%}.hvs__cl--b{width:15%;top:24%;left:52%;animation-name:hvs-cl2}
.hvs__gr{left:0;right:0;bottom:0;height:16%;background:#2b2724}
.hvs__bld{left:22%;width:30%;bottom:16%;height:62%;display:flex;flex-direction:column-reverse;gap:2%}
.hvs__bld i{display:block;flex:1;background:linear-gradient(#0a0a0a 0 22%,transparent 22% 78%,#0a0a0a 78%),repeating-linear-gradient(90deg,#0a0a0a 0 9px,#ffcfb8 9px 15px);transform-origin:bottom;animation:hvs-fl .6s cubic-bezier(.2,.8,.2,1) both;animation-delay:calc(.5s + var(--f) * .95s)}
.hvs__bld2{left:58%;width:16%;bottom:16%;height:26%;background:#3a3430;animation:hvs-b2 8s linear both}
.hvs__crane{right:10%;bottom:16%;width:6%;height:80%}
.hvs__mast{position:absolute;left:40%;width:20%;top:0;bottom:0;background:repeating-linear-gradient(0deg,#0a0a0a 0 2px,transparent 2px 7px),linear-gradient(90deg,#0a0a0a 0 2px,transparent 2px calc(100% - 2px),#0a0a0a 0)}
.hvs__jib{position:absolute;top:0;right:50%;width:780%;height:3px;background:#0a0a0a;transform-origin:100% 50%;animation:hvs-jib 8s ease-in-out both}
.hvs__cab{position:absolute;right:-6px;top:-5px;width:10px;height:9px;background:#F5480F}
.hvs__load{position:absolute;left:30%;top:3px;width:1px;height:28px;background:#0a0a0a;animation:hvs-load 8s ease-in-out both}
.hvs__load::after{content:"";position:absolute;left:-5px;bottom:-7px;width:11px;height:7px;background:#F5480F}
@keyframes hvs-sky{from{background-position:0 0}to{background-position:0 100%}}
@keyframes hvs-sun{0%{left:8%;top:72%}50%{left:44%;top:10%}100%{left:84%;top:66%}}
@keyframes hvs-cl{from{transform:translateX(0)}to{transform:translateX(320%)}}
@keyframes hvs-cl2{from{transform:translateX(0)}to{transform:translateX(-240%)}}
@keyframes hvs-fl{from{transform:scaleY(0);opacity:0}to{transform:none;opacity:1}}
@keyframes hvs-b2{0%,55%{transform:scaleY(.15);transform-origin:bottom}100%{transform:none;transform-origin:bottom}}
@keyframes hvs-jib{0%{transform:rotate(-4deg)}25%{transform:rotate(9deg)}50%{transform:rotate(-2deg)}75%{transform:rotate(12deg)}100%{transform:rotate(0)}}
@keyframes hvs-load{0%,100%{height:12px}20%{height:40px}45%{height:16px}70%{height:46px}}
.hvs__tag{position:absolute;left:8px;top:8px;font:600 9px 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase;background:#0a0a0a;color:#fff;padding:3px 6px;border-radius:3px}
.hvs__pl{position:absolute;left:50%;top:50%;width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;background:#fff;color:#0a0a0a;display:grid;place-items:center;transition:opacity .25s,transform .25s;box-shadow:0 6px 18px -8px rgba(0,0,0,.5)}
.hvs.is-play .hvs__pl{opacity:0;transform:scale(.7)}
.hvs__ui{position:absolute;left:8px;right:8px;bottom:7px;display:flex;align-items:center;gap:8px}
.hvs__tc{font:600 9.5px 'JetBrains Mono',monospace;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 1px 2px rgba(0,0,0,.5);white-space:nowrap}
.hvs__pb{flex:1;height:3px;border-radius:3px;background:rgba(255,255,255,.35);overflow:hidden}
.hvs__pf{display:block;height:100%;width:0;background:#F5480F}
.hvs__meta{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:12.5px}
.hvs__meta b{font-weight:700;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hvs__meta span{font:500 9.5px 'JetBrains Mono',monospace;color:#6b6762;white-space:nowrap}
@container (max-width:380px){.hvs__meta span{display:none}}// Video-preview bij hover · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.hvs')||root;
var media=root.querySelector('.hvs__media'),tc=root.querySelector('.hvs__tc'),pf=root.querySelector('.hvs__pf');
var DUR=8000,t=3300,play=false,last=0;
var anims=(root.querySelector('.hvs__scene').getAnimations?root.querySelector('.hvs__scene').getAnimations({subtree:true}):[]);
anims.forEach(function(a){a.pause();});
function draw(){anims.forEach(function(a){a.currentTime=t;});pf.style.width=(t/DUR*100).toFixed(2)+'%';tc.textContent='0:0'+Math.floor(t/1000)+' / 0:08';}
function loop(now){if(!play)return;var dt=last?now-last:16;last=now;t=(t+dt)%DUR;draw();requestAnimationFrame(loop);}
function start(){if(play)return;play=true;last=0;root.classList.add('is-play');media.setAttribute('aria-label','Pauzeer timelapse');requestAnimationFrame(loop);}
function stop(){play=false;root.classList.remove('is-play');media.setAttribute('aria-label','Speel timelapse af');}
var rm=matchMedia('(prefers-reduced-motion: reduce)').matches;
media.addEventListener('pointerenter',function(e){if(e.pointerType==='mouse'&&!rm)start();});
media.addEventListener('pointerleave',function(e){if(e.pointerType==='mouse')stop();});
media.addEventListener('pointermove',function(e){if(e.pointerType!=='mouse')return;var r=media.getBoundingClientRect();t=Math.max(0,Math.min(DUR-1,(e.clientX-r.left)/r.width*DUR));draw();});
media.addEventListener('click',function(e){if(e.pointerType==='mouse'&&!rm)return;play?stop():start();});
media.addEventListener('keydown',function(e){if(e.key===' '||e.key==='Enter'){e.preventDefault();play?stop():start();}if(e.key==='ArrowRight'){t=Math.min(DUR-1,t+500);draw();}if(e.key==='ArrowLeft'){t=Math.max(0,t-500);draw();}});
draw();
}
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 →