HTML and CSS Reference
A race to play video
Here's where I tell you that as much as native video and audio
smells of roses, there's a certain pong coming from somewhere.
That somewhere is a problem in the implementation of the
media element that creates what's known as a “race condition.”
A race, what now?
In this situation, the race condition is where an expected sequence of
events fires in an unpredicted order. In particular, the events fire before
your event handler code is attached.
The problem is that it's possible, though not likely, for the
browser to load the media element before you've had time to
bind the event listeners.
For example, if you're using the loadedmetadata event to listen
for when a video is ready so that you can build your own fancy-
pants video player, it's possible that the native video HTML ele-
There are a few workarounds for this race condition, all of which
would be nice to avoid, but I'm afraid it's just something we
need to code for defensively.
WORKAROUND #1: HIGH EVENT DELEGATION
In this workaround, we need to attach an event handler on the
window object. This event handler must be above the media ele-
ment. The obvious downside to this approach is that the script
element is above our content, and risks blocking our content
from loading (best practice is to include all script blocks at the
end of the document).
Nonetheless, the HTML5 specification states that media events
should bubble up the DOM all the way to the window object. So
when the loadedmetadata event fires on the window object, we
check where the event originated from, via the target property,
and if that's our element, we run the setup code. Note that in
the example below, I'm only checking the nodeName of the ele-
ment; you may want to run this code against all audio elements
or you may want to check more properties on the DOM node
to make sure you've got the right one.