'Remove a <video> element if the video fails to autoplay on iOS low power using javascript
I have this video header I want to use on my website (for the sake of this demo I'm using the bunny video from W3 that anybody can access). The header will autoplay and just serve as a header with no controls or audio.
The problem I'm facing is well-documented in that if a video fails to autoplay on iOS it shows a huge play button instead of just the poster image. I've tried every solution under the sun to hide the button and nothing has worked so now I'm trying to remove the video element altogether if it doesn't play and let a fallback image load behind the video instead. The image is already loaded and sitting behind the video with a z-index of -1 so all I have to do is find a way to remove the video when it fails to autoplay on low battery mode.
I can't use a gif for this because they're huge and exceed the max size of uploaded content in this instance and using a huge gif on a mobile device seems like a bad idea anyway.
So I've built a container to hold the <video> as well as the fallback image inside of a div which are both positioned absolutely so that I can hide the fallback image.
I think my logic (if video doesn't autoplay on load then remove video else autoplay video) is correct, I just think I don't know enough about javascript to pull off what I'm attempting. I'm open to any method of doing this. I've tried removing the src attribute but iOS still knows it's a video (probably because of the video tag) so I just end up at the same result with no video source. I've also tried using the addEventListener('suspend' (event) => { method but it seems to suspend the video no matter what power state the device is in (and on the desktop for that matter). I thought that Apple was using suspend to prevent autoplay but I think it might be using the play or paused states instead (I can't verify one way or the other and the Apple docs weren't explicit on that so feel free to correct me especially if you find a source for it!).
https://jsfiddle.net/astombaugh/7tj01hxm/528/
<body>
<div class="videoHeaderContainer" id="videoHeaderContainer">
<video id="videoHeader" class="videoHeader" src="https://www.w3schools.com/tags/mov_bbb.mp4" loop muted autoPlay playsInline type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'">
</video>
<div class="videoHeaderFallBackImg" id="videoHeaderFallBackImg"></div>
</div>
</body>
.videoHeaderContainer {
display: block;
position: relative;
width: 100%;
height: auto;
max-width: 1345px !important;
padding: 0rem 0rem 0rem 0rem;
margin: 0rem auto 0.4375rem auto;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.6);
}
.videoHeader {
display: block;
position: absolute;
object-fit: cover;
max-width: 1345px;
width: 100%;
height: auto;
margin: 0 auto;
border: 1px solid black;
}
.videoHeaderFallBackImg {
content: url("https://i.imgur.com/Vr1RMST.jpg");
display: block;
position: absolute;
object-fit: cover;
max-width: 1345px;
width: 100%;
height: auto;
margin: 0 auto;
z-index: -1;
border: 1px solid black;
}
//replace video on low power mode
function removeVideo() {
const videoHeaderContainer = document.getElementById('videoHeaderContainer');
const videoHeader = document.getElementById('videoHeader');
if (videoHeader.paused == "") {
videoHeaderContainer.removeChild(videoHeaderContainer.children[0]);
} else {
videoHeader.play();
}
}
Edit 03/29:
So I know removechild DOES work with this as it works as a standalone command and leaves only the videoHeaderFallBackImg visible (if you move that line after the const you'll see the video disappear. What I can't figure out is why it's not working in the context of my JS expression.
I've tried simplifying it down to this:
const videoHeader = document.querySelector('#videoHeader');
videoHeader.addEventListener('stalled', (event) => {
videoHeader.parentElement.removeChild(videoHeaderContainer.children[0]);
});
This still doesn't work but leads me to believe that the addEventListener is the key. I can't seem to find anywhere that Apple specifics which eventListener they're using for low power mode on iOS and I also can't seem to find a way to inspect what's happening on a mobile device unless I have my iPhone attached to a Mac and use Safari's debugger which I don't have access to. I tried using BrowserStack but unfortunately there doesn't seem to be a way to enable low power mode on their devices.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
