Mazzarolo MatteoMazzarolo Matteo

Ouch, Safari on iOS can overlap multiple full-screen videos

By Mazzarolo Matteo


I recently discovered (by mistake) a potentially irritating behavior of Safari on iOS: full-screen videos can overlap each other:

Nope, the video above it's not broken. That's exactly what you see when multiple full-screen videos overlap.

I assume this is a bug, right? As a user, I can't think of cases where I'd want to open more than a single full-screen video.

The most annoying part of this behavior is that, if done on purpose, websites can easily open dozens of videos simultaneously. Thanks to slow iOS animations, good luck closing 30+ full-screen videos. It's easier and faster just to force close Safari... and, if you're lucky enough, you might not even have to close it since sometimes this behavior makes Safari crash.

All it takes for a website to show multiple videos in full screen is to use JavaScript to invoke the HTMLMediaElement.play() method on multiple video elements after a user interaction.
The "after a user interaction" part is important here: browsers generally only allow autoplay (as in playing audio without the user explicitly requesting it) to occur successfully under specific circumstances, such as interacting with buttons.

I know, I know, after all this talking, you wanna try this magical behavior yourself. So here's a tiny web page I created to play with it.

If you're interested, the page shows a button that runs the following code when pressed:

// Create a bunch of video elements.
let videoElementStrings = ``;
for (let i = 0; i < 30; i++) {
  videoElementStrings += `<video src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" type="video/mp4"></video>`;
}
document.getElementById("video-elements-root").innerHTML = videoElementStrings;
// Play each video element.
// Scheduling this flow using macrotasks seems to provide more consitent results
// for me (hence the setTimeout), but it might just be a placebo effect.
setTimeout(function () {
  document.querySelectorAll("video").forEach((videoElement) => {
    setTimeout(function () {
      videoElement.play();
    }, 0);
  }, 0);
});
// Create a bunch of video elements.
let videoElementStrings = ``;
for (let i = 0; i < 30; i++) {
  videoElementStrings += `<video src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" type="video/mp4"></video>`;
}
document.getElementById("video-elements-root").innerHTML = videoElementStrings;
// Play each video element.
// Scheduling this flow using macrotasks seems to provide more consitent results
// for me (hence the setTimeout), but it might just be a placebo effect.
setTimeout(function () {
  document.querySelectorAll("video").forEach((videoElement) => {
    setTimeout(function () {
      videoElement.play();
    }, 0);
  }, 0);
});

I haven't investigated in depth why this is happening, nor how other mobile browsers and OS behave. Still, if I had to guess, I'd say Safari is not checking if there's another resource that already obtained the full-screen control (given that the full-screen request is an asynchronous operation).

I reported the bug in the WebKit Bugzilla tracker here.