Let's say you're using early 2000s web tech to speed up page transitions, but with slightly newer APIs. When a link is clicked, the new page is loaded asynchronously (for example with fetch). Then a subsection of the current page is replaced by (a subsection of) the new page, using replaceWith (or replaceChild or a similar method depending on the implementation. There are many out there).

It looks like Safari has some trouble when that new page contains a video element.

I encountered this bug with a video element which defines a poster image, enables native controls and asks the browser to preload the metadata.

<video preload="metadata" poster="thumbnail.jpeg" controls>
  <source src="video.mp4">
</video>

Safari displays the poster image after navigating to the new page, but it does not show the video controls. A quick look at the developer tools reveals that it also does not make any network requests to preload the metadata. On the other hand it's still possible to programmatically load and play the video from the developer tools console.

Firefox and Chrome don't have this problem. Also, everything works normally after reloading the page in Safari, but that defeats the purpose of the speed optimization.

It looks like this is related to how the video element is inserted into the page. The bug occurs with replaceWith, but also with replaceChild and re-implementations with insertAjacentHTML, insertBefore or appendChild.

I couldn't find any information about this online except a passing comment from 2012.

What I did find out after experimenting some more is that the unsafe innerHTML (or its companion outerHTML) fixes the bug.

I would not replace the entire page with innerHTML. However the part with the video contains no user input. My workaround is to continue using replaceWith, but then refresh only the video elements:

document.querySelectorAll('video').forEach((video) => {
  const content = video.outerHTML;
  video.outerHTML = content;
})

This removes event handlers from the "reset" video element, so I also needed to re-attach those.