Below is the GSAP JavaScript code that creates the effect. This needs to be put into an Elementor HTML widget BELOW the video you’re applying the effect to. It should work without you needing to add any IDs or Classes to the video widget in Elementor. If you run into problems, refer to the video above. If you would prefer to SKIP all the work and IMPORT this functionality into your site with just a few clicks, you can purchase this section below.
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.3/ScrollTrigger.min.js"></script>
<script>
/* Code written by Bjorn from WPLearningLab. Check out my WordPress YouTube channel for more awesome videos, code and webdesign inspiration! */
document.addEventListener('DOMContentLoaded', function() {
console.clear();
const video = document.querySelector('video');
video.classList.add('video-background');
const src = video.currentSrc || video.src;
// Function to add an event listener that triggers only once
function addOnceEventListener(element, event, handler, options) {
function eventHandler(e) {
element.removeEventListener(event, eventHandler);
handler(e);
}
element.addEventListener(event, eventHandler, options);
}
// Activate video on iOS
addOnceEventListener(document.documentElement, "touchstart", () => {
video.play();
video.pause();
});
gsap.registerPlugin(ScrollTrigger);
// GSAP ScrollTrigger timeline
const tl = gsap.timeline({
scrollTrigger: {
trigger: "#container",
start: "top top",
end: "bottom bottom",
scrub: true
}
});
addOnceEventListener(video, "loadedmetadata", () => {
tl.fromTo(video, { currentTime: 0 }, { currentTime: video.duration || 1 });
});
// Fetch and replace video source for iOS
setTimeout(() => {
if ('fetch' in window) {
fetch(src)
.then(response => response.blob())
.then(blob => {
const blobURL = URL.createObjectURL(blob);
const currentTime = video.currentTime;
video.src = blobURL;
video.currentTime = currentTime + 0.01;
addOnceEventListener(document.documentElement, "touchstart", () => {
video.play();
video.pause();
});
});
}
}, 1000);
});
</script>
Below is the ffmpeg code needed to render the perfect MP4 file for this effect to the best. Credit for this code goes to Cassie from the GSAP forum.
ffmpeg -i input.mp4 -movflags faststart -vcodec libx264 -crf 23 -g 1 -pix_fmt yuv420p output.mp4
If you’re unable to get the ffmpeg code to work you can still create this effect, but it may be a little jumpy. The most important things you need to make sure of is that the video file is an MP4 and that it is 30 frames per second. You can find online tools like this one that will convert your video to MP4 and make it 30 frames per second for free.