Table of content
This week, I had a user story to add a video mode to a card that displays some content. One of the acceptance criteria was that the video must start playing when the user scrolls down, and the card reaches the center of the screen.
It turned out to be simpler than I expected. Here’s how you can do it too.
Using IntersectionObserver
To detect if an element intersects with another (including the viewport), you can use an IntersectionObserver
like this:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.play(); // Start video playback
} else {
entry.target.pause(); // Pause video when out of view
}
});
}, {
root: document.querySelector("#scrollArea"),
rootMargin: "0px",
threshold: 0.5
});
observer.observe(document.querySelector(".video-card video"));
Understanding the Configuration
- root: This defines the ancestor of the target element. If set to
null
, it defaults to the viewport. - rootMargin: Adjusts the margin around the root. Should be adapted for desktop and mobile devices.
- threshold: A value between
0
and1
that represents the percentage of visibility required to trigger the observer's callback. In this case,1.0
means the entire element must be in view.
The example
In my case, as I wanted the card to start reproducing the video only while its in the center (on mobile), I had to adjust the rootMargin property like so:
...
rootMargin: "-35% 0px -35% 0px",
...
With that values we can leave space at the top and bottom of the viewport and only match elements that are visible in the center.
And the result was something like this:With this setup, only one card at a time will play its video when it's centered on the screen. 🎥✨
Full code:
document.addEventListener('DOMContentLoaded', () => {
const videos = document.querySelectorAll('video');
const options = {
root: null,
rootMargin: '-35% 0px -35% 0px',
threshold: 0.5
};
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
const video = entry.target;
if (entry.isIntersecting) {
video.play();
} else {
video.pause();
}
});
}, options);
videos.forEach(video => {
observer.observe(video);
});
});
I hope you have learned something new from all. If you think this might help other people, please hit the like button so that others can read it. ❤️
If you have any thoughts or questions, feel free to leave a comment!