JS/CSS — Transition effect for looping background video

Liu Ting Chun
2 min readFeb 26, 2022

Using videos as the background is a common practice nowadays for creative web design. However, most videos are not self-looped. There is a flicking of frames when those videos are repeated, which is simply — ugly.

Repeating a video that is not self-looped.

This issue can be solved by simply adding a transition effect at the end of the video, and it is extremely easy to do that. We don’t need any video editing software. The solution needs only JS and CSS. Besides, it is universal. That single function will work for all videos. Fine-tuning is not required.

Video with transition effect

The Code

Let’s keep it short for simplicity. To begin with, instead of letting the video play and repeat itself, we need to write a function to manage the loop mechanism such that we can add and remove a CSS class in between.

function playVideo(e) {
e.play();
e.classList.remove('fading');
setTimeout(() => {
e.classList.add('fading');
}, (e.duration / e.playbackRate - 1) * 1000)
}

We calculate the video length and add the fading CSS class 1 second (you can change this value if you want a longer transition) before the end of the video.

After that, in the HTML, we do:

<video 
class="transition fading"
muted
autoplay
playsinline
onloadedmetadata="this.muted = true"
oncanplay="playVideo(this)"
onended="playVideo(this)">
<source src="./sample.mp4">
</video>

Finally, we define the transition effect with CSS:

.transition {
transition: all 1s;
}

.transition.fading {
opacity: 0;
}

One point to remind here is the transition time MUST equal to the value defined at the JS. For example, if you add the fading 2 seconds before the end of the video i.e. (e.duration / e.playbackRate - 2) * 1000, the transition time here has to be 2 as well, i.e. transition: all 2s;.

Also, note that the default behavior is to fade with the parent background color. Hence, if you want to have a different one, you could wrap the element with a div:

<div style="display: inline-block; background-color: black">
<video
class="transition fading"
muted
autoplay
playsinline
onloadedmetadata="this.muted = true"
oncanplay="playVideo(this)"
onended="playVideo(this)">
<source src="./sample.mp4">
</video>
</div>

That’s all! We now have a loop transition effect that works universally for all kinds of videos.

Thanks for reading! Hope you find this article helpful. Any comments would be highly appreciated. :D

--

--

Liu Ting Chun

Web developer from Hong Kong. Most interested in Angular and Vue. Currently working on a Nuxt.js + NestJS project.