Is there anyway to autoplay a HTML5 video only when the user has the video (or a certain percentage of the video) in the browser viewport?
-
You can have a div with display none...and if the age of that person is correct then add the video tag with the video source in the div and change the display to block....if this is what you want i could help you...simple show me the way you want to retrieve the age of the visitor and that's it xD – Hackerman Mar 13 '13 at 20:37
5 Answers
In brief
Let's say our browser window W
currently scrolled to y-position scrollTop
and scrollBottom
Our video will NOT be played when its position is at V1
or V2
as below snapshot.
Code details
$(document).ready(function() {
// Get media - with autoplay disabled (audio or video)
var media = $('video').not("[autoplay='autoplay']");
var tolerancePixel = 40;
function checkMedia(){
// Get current browser top and bottom
var scrollTop = $(window).scrollTop() + tolerancePixel;
var scrollBottom = $(window).scrollTop() + $(window).height() - tolerancePixel;
media.each(function(index, el) {
var yTopMedia = $(this).offset().top;
var yBottomMedia = $(this).height() + yTopMedia;
if(scrollTop < yBottomMedia && scrollBottom > yTopMedia){ //view explaination in `In brief` section above
$(this).get(0).play();
} else {
$(this).get(0).pause();
}
});
//}
}
$(document).on('scroll', checkMedia);
});

- 33,193
- 69
- 233
- 372

- 311
- 3
- 2
-
4
-
9Mikkel's solution is explained in the commented out text. It's elegant and it works. Plus I like that it uses jQuery. Thanks Mikkel! – soulphysics Nov 23 '14 at 16:24
-
-
That's great, it's helped me a lot! It's no biggie but is there a way to make `tolerancePixel` a percentage? Also is it possible to display a "play again" button once the video has finished? – user1406440 Oct 25 '17 at 16:26
hope this helps but it has been answered before
var videos = document.getElementsByTagName("video"),
fraction = 0.8;
function checkScroll() {
for(var i = 0; i < videos.length; i++) {
var video = videos[i];
var x = video.offsetLeft, y = video.offsetTop, w = video.offsetWidth, h = video.offsetHeight, r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);

- 286
- 4
- 10
You can use window.pageXOffset and window.pageYOffset to check how far your browser window is scrolled both vertically and horizontally. Use these with window.innerWidth
and innerHeight
and some basic geometry math to calculate how much your visible page overlaps with the video itself. Put this all in a function that you can attach to the scroll
and resize
event on the window object to run the check every time the scrolling changes.
Here is some sample code:
var video = document.getElementById('video'),
info = document.getElementById('info'),
fraction = 0.8;
function checkScroll() {
var x = video.offsetLeft,
y = video.offsetTop,
w = video.offsetWidth,
h = video.offsetHeight,
r = x + w, //right
b = y + h, //bottom
visibleX,
visibleY,
visible;
if (window.pageXOffset >= r ||
window.pageYOffset >= b ||
window.pageXOffset + window.innerWidth < x ||
window.pageYOffset + window.innerHeight < y
) {
info.innerHTML = '0%';
return;
}
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
info.innerHTML = Math.round(visible * 100) + '%';
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
//one time at the beginning, in case it starts in view
checkScroll();
//as soon as we know the video dimensions
video.addEventListener('loadedmetadata', checkScroll, false);
And a working example.
This code assumes a pretty simple page layout. If your video is positioned absolutely inside another element that has "position: relative" set, then you'll need to do a little more work to calculate the correct position of the video. (The same goes if the video has been moved with CSS transforms.)

- 7,661
- 1
- 32
- 32
-
I was assuming that the question was to play once a certain percentage of the video was downloaded. I didn't read it that closely I guess – Jason Sperske Mar 13 '13 at 21:38
-
Yes. You can use `$` instead of getElementById, and `$('#video').bind(...` instead of addEventListener. You can use ".offset()" if you want. – brianchirls Mar 14 '13 at 00:41
There is a new API for this scenario, called Intersection_Observer_API, which Chrome 51+ and Edge 15+ has supported.
var options = {
root: document.querySelector('.scroll-container'),
rootMargin: '0px',
threshold: 1.0 // trigger only when element comes into view completely
};
var ob = new IntersectionObserver((entries, observer) => {
entries[0].target.classList.toggle('red');
}, options);
// observe all targets, when coming into view, change color
document.querySelectorAll('.target').forEach((item) => {
ob.observe(item);
});
Here is a simple demo: https://codepen.io/hectorguo/pen/ybOKEJ

- 1,011
- 12
- 9
This pure javascript solution worked for me:
// is visible function
function isVisible(elem) {
if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
const style = getComputedStyle(elem);
if (style.display === 'none') return false;
if (style.visibility !== 'visible') return false;
if (style.opacity < 0.1) return false;
if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
elem.getBoundingClientRect().width === 0) {
return false;
}
const elemCenter = {
x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
};
if (elemCenter.x < 0) return false;
if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
if (elemCenter.y < 0) return false;
if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
do {
if (pointContainer === elem) return true;
} while (pointContainer = pointContainer.parentNode);
return false;
}
// on window load start checking on scroll
window.onload = function() {
var videos = document.getElementsByTagName("video")
function checkScroll() {
for(var i = 0; i < videos.length; i++) {
var video = videos[i];
if(isVisible(video)){
video.play();
}else{
video.pause()
}
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
}
isVisible function is from other solution: answer for checking visible elements on stackoverflow

- 482
- 4
- 8