if I have the video component playing a video and I scroll down, how do I silence the audio from the video automatically?
If it’s a YouTube video, you can pause it when it scrolls out of the viewport, adding this to the javascript section of the page code editor.
Note on line 3 “myvideo”
You need to select the video, go to advanced setting and add myvideo as the id.
document.addEventListener('DOMContentLoaded', () => {
gsap.registerPlugin(ScrollTrigger);
const container = document.getElementById('myvideo');
if (!container) return;
let iframe = null;
let apiReady = false;
const observer = new MutationObserver(() => {
const found = container.querySelector('iframe');
if (found && !apiReady) {
iframe = found;
setupIframeApi(iframe);
apiReady = true;
observer.disconnect();
}
});
observer.observe(container, { childList: true, subtree: true });
function setupIframeApi(iframeEl) {
let src = iframeEl.getAttribute('src') || '';
if (!src) return;
try {
const url = new URL(src, window.location.origin);
url.searchParams.set('enablejsapi', '1');
iframeEl.src = url.toString();
} catch (e) {
if (!/enablejsapi=1/.test(src)) {
const sep = src.includes('?') ? '&' : '?';
iframeEl.src = src + sep + 'enablejsapi=1';
}
}
}
function pauseYoutube() {
if (!iframe) {
iframe = container.querySelector('iframe');
if (!iframe) return;
}
iframe.contentWindow?.postMessage(
JSON.stringify({
event: 'command',
func: 'pauseVideo',
args: []
}),
'*'
);
}
ScrollTrigger.create({
trigger: container,
start: 'top bottom',
end: 'bottom top',
onLeave() {
pauseYoutube();
},
onLeaveBack() {
pauseYoutube();
}
});
});
There was a slight bug there and it only worked second time it left the viewport. Fixed and updated code above.
Thank you. it’s an embedded video component in elements.
Yes, but is it a YouTube video or an mp4 you’re using inside it. If you tube above will work, if mp4 use this instead.
document.addEventListener('DOMContentLoaded', () => {
gsap.registerPlugin(ScrollTrigger);
const container = document.getElementById('myvideo');
if (!container) return;
let video = container.querySelector('video');
const observer = new MutationObserver(() => {
const found = container.querySelector('video');
if (found) {
video = found;
observer.disconnect();
}
});
observer.observe(container, { childList: true, subtree: true });
function stopMp4() {
if (!video) return;
video.pause();
video.currentTime = 0;
}
ScrollTrigger.create({
trigger: container,
start: 'top bottom',
end: 'bottom top',
onLeave() {
stopMp4();
},
onLeaveBack() {
stopMp4();
}
});
});
If you were hoping for a no code way, there isn’t one I am afraid.
Thanks for all your help!
in case you dont know where to find it its here
And dont forget to select teh video component and give it an id of myvideo
Yes I didn’t know–thanks for thinking ahead for me.
It works–thanks!! Might be pushing it, but is there a way to stop audio if scrolled down or up?
so you want to stop audio but keep the video playing out of view?
Just to be sure, when you say it works? it should be currently pausing teh video, which obviously also stops the audio.
And which are you using? YouTube or MP4?
Close to top of page I have an mp4 that starts playing w/sound in viewport and now with your code, once scrolled past the sound stops. If I scroll back up to the mp4 it doesn’t run (even though I have it set to loop). It’s ok that way but wondering if the mp4 (or a YouTube) would only play with sound while in viewport getting there scrolling down or up? Don’t need to take time to help, you did a lot already; sharing more detail for the elements team maybe they can add this feature in future releases.
Yeah, Once stopped on scroll out, it would be tricky to make it play again when scrolled back into view. I could make it play again when scrolled back into view, the tricky part would be know if it was playing when it left, else every video that scrolled into view would just start playing.
I say every video, as I made a better universal version which will also work if you have multiple videos on the page. It now uses class instead of Id, and works with either YouTube or MP4
Now just add the class video-stopper to any video on the page you want to stop playing when it’s scrolled out of view.
document.addEventListener('DOMContentLoaded', () => {
gsap.registerPlugin(ScrollTrigger);
const containers = document.querySelectorAll('.video-stopper');
if (!containers.length) return;
containers.forEach(container => {
let video = container.querySelector('video');
let iframe = container.querySelector('iframe');
const observer = new MutationObserver(() => {
if (!video) video = container.querySelector('video');
if (!iframe) iframe = container.querySelector('iframe');
if (iframe) ensureYouTubeApi(iframe);
if (video || iframe) observer.disconnect();
});
if (!video && !iframe) {
observer.observe(container, { childList: true, subtree: true });
}
function ensureYouTubeApi(iframeEl) {
const raw = iframeEl.getAttribute('src');
if (!raw) return;
const hasApi = raw.includes('enablejsapi=1');
if (!hasApi) {
const sep = raw.includes('?') ? '&' : '?';
iframeEl.src = raw + sep + 'enablejsapi=1';
}
}
function pauseYouTube(iframeEl) {
if (!iframeEl) return;
iframeEl.contentWindow?.postMessage(
JSON.stringify({ event: "command", func: "pauseVideo", args: [] }),
"*"
);
}
function stopMp4(videoEl) {
if (!videoEl) return;
videoEl.pause();
videoEl.currentTime = 0;
}
ScrollTrigger.create({
trigger: container,
start: "top bottom",
end: "bottom top",
onLeave() {
if (iframe) pauseYouTube(iframe);
if (video) stopMp4(video);
},
onLeaveBack() {
if (iframe) pauseYouTube(iframe);
if (video) stopMp4(video);
}
});
});
});
No problem. Its a handy little script, I will use in my own pages.
Nailed it! that you so much!
One last question - have you come up with a workaround for not dimming on hover on an embedded mp4 with controls? If I remove controls then the video is not affected by the mouse over. But I need the controls to restart the video upon scrolling back up to it.
No, Thats either browser chrome, or part of the html5 native player. It would require disabling controls and building a custom set of controls without an overlay. Out of the scope of this thread I am afraid.
