Play Video on Hover (Lazy)
Category: Video & Audio. Last updated: Aug 20, 2025
Code
<div data-video-on-hover="not-active" data-video-src="https://osmo.b-cdn.net/resource-video/whatsapp-modal-1440x900.mp4" class="video-card">
<div class="video-card-visual">
<img src="https://cdn.prod.website-files.com/68493e75b2d7f03a5fa360af/68495579840e207fe2517a41_video-card-1.avif" class="video-card-visual__img">
<video muted loop webkit-playsinline playsinline src="" class="video-card-visual__video"></video>
</div>
<span class="video-card-title">WhatsApp Modal</span>
</div>.video-card {
gap: 1em;
background-color: #f0f0f0;
border-radius: .75em;
flex-flow: column;
width: 22em;
padding: .75em .75em 1.125em;
transition: background-color .2s;
display: flex;
}
.video-card:hover {
background-color: #fff;
}
.video-card-visual {
aspect-ratio: 1.6;
border-radius: .5em;
width: 100%;
position: relative;
overflow: hidden;
}
.video-card-visual__img {
object-fit: cover;
width: 100%;
height: 100%;
}
.video-card-visual__video {
opacity: 0;
width: 100%;
height: 100%;
padding: 0;
transition: opacity .2s;
position: absolute;
inset: 0%;
}
.video-card-title{
padding-left: 0.75em;
}
/* ———— If video is active and hovered, set it to opacity 1 ———— */
[data-video-on-hover="active"] video{ opacity: 1; }
/* ———— If video is active and hovered, set it to opacity 1 ———— */
[data-video-on-hover="active"] video{ opacity: 1; }function initPlayVideoHover() {
const wrappers = document.querySelectorAll('[data-video-on-hover]');
wrappers.forEach(wrapper => {
const video = wrapper.querySelector('video');
const src = wrapper.getAttribute('data-video-src') || '';
if (!video || !src) return;
wrapper.addEventListener('mouseenter', () => {
if (!video.getAttribute('src')) {
video.setAttribute('src', src);
}
wrapper.dataset.videoOnHover = 'active';
video.play().catch(err => {
console.warn('play on hover is blocked:', err);
});
});
wrapper.addEventListener('mouseleave', () => {
wrapper.dataset.videoOnHover = 'not-active';
setTimeout(() => {
video.pause();
video.currentTime = 0;
}, 200);
});
});
}
document.addEventListener("DOMContentLoaded", () => {
initPlayVideoHover();
});Guide
Documentation
A lightweight, dependency-free component that displays a placeholder image and seamlessly transitions to a video on hover. Perfect for dynamic previews and interactive components without slowing down your page speed. Videos are created on-demand, by only fetching and serving when a user hovers over the card.
HTML Structure
Add data-video-on-hover to any wrapper element of your HTML5 video element. This is the attribute that the code will target for hover events. We will also toggle an active or not-active value on this attribute to control the opacity of a placeholder image.To that same wrapper element add an attribute of data-video-src and include a link to your (mp4) video in the attribute value. Once a user hovers the wrapper, we will load the video src dynamically and play!To our video element inside, make sure to include the following attributes:muted: Required for autoplay browser policy.loop: Optional of course.playsinline / webkit-playsinline: Ensure inline mobile playback.We will define opacity: 0 to our video in CSS.
JavaScript
Hover InOn first hover, sets video.src from data-video-src. This only needs to happen once, on every hover after that, we can simply call play()Updates data-video-on-hover to "active". In our CSS we use this to set our video to opacity: 1Calls video.play(), silently catching any rejection.Hover OutUpdates data-video-on-hover to "not-active". This will hide our video again.After a 200 ms delay, pauses playback and resets currentTime to 0. That's it! A simple, no-dependency way to add engaging video previews to your cards.
Hosting your own videos
We recommend checking the video attached to this resource, in which Ilja explains step-by-step how to setup your own video hosting at Bunny.net. It takes a couple of minutes to set up a super fast, cheap, and reliable service for yourself and/or clients. Always make sure to compress your videos before uploading, by using a website like videosmaller.com or a tool like Handbrake.