When using DOMParser
, <video>
tag is not working in Safari, its preview is rendered but without controls and without the ability to play:
const parser = new DOMParser() const parsed = parser.parseFromString( document.querySelector('video').outerHTML, 'text/html' ) document.body.appendChild(parsed.querySelector('body').childNodes[0])
<video width="250" controls playsinline src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4#t=0.001" ></video>
The code above works as expected in Chrome:
But Safari renders this (both macOS and iOS):
There are no controls and it’s impossible to play the second video which was produced by DOMParser.
Is that some kind of security feature or a bug? Is there any workaround for this behavior?
Advertisement
Answer
This is a Bug
Here’s a link to the webkit bug ticket.
comment #6 (2021-03-04 22:50:29 PST):
[…] media element not initialize its UA shadow root when it’s created inside a document without a browsing context. The fix is to initialize the media element controls once it’s inserted into a document with a browsing context.
comment #12 (2022-08-02 11:16:50 PDT): Pull request: https://github.com/WebKit/WebKit/pull/2955
comment #13 (2022-08-08 11:47:08 PDT): Committed
253225@main (f331cc98c1de)
: https://commits.webkit.org/253225@main Reviewed commits have been landed. Closing PR #2955 and removing active labels.
Here’s a Workaround
// keep doing what you were doing: const parser = new DOMParser() const parsed = parser.parseFromString( document.querySelector('video').outerHTML, 'text/html' ); const child = document.body.appendChild(parsed.querySelector('body').childNodes[0]); // but then force the media elements to reload afterward: [child].concat(Array.from(child.querySelectorAll("video, audio"))) .forEach(e => e.outerHTML = e.outerHTML);
There are other workarounds like the cloneNode
one that @Tibic4 suggested, but I think this one is nice in that you can still keep using DOMParser
for most of the work.
Once the webkit fix gets deployed you won’t need the workaround for any of the Safari versions where the fix gets applied. Hopefully it gets reasonably backported.