HTML5 video for retina displays

Recently I came across a question on Stack Overflow where a user wanted to serve a high resolution video to devices that supported retina displays. I had half a solution.

I guessed that the user hadn’t heard of the media attribute of the source element, which allows you to specify different sources providing a certain media query is met. I wrote about this a while back in an article on responsive HTML5 video.

This is only half the solution though, as we also need a media query that actually tells us that a device/browser has a retina display. I didn’t know of one and posted the question in my answer to the same Stack Overflow question linked to above.

Paul D. Waite promptly replied, bringing min-device-pixel-ratio to my attention.

As Chris Coyier’s article shows, a value of 2 matches a retina device, so we can specify a retina video like this:

<video controls> 
   <source type='video/mp4' src='video-high-res.mp4' media='(min-device-pixel-ratio:2)'> 
   <source type='video/webm' src='video-high-res.webm' media='(min-device-pixel-ratio:2)'> 
   <source type='video/mp4' src='video.mp4'> 
   <source type='video/webm' src='video.webm'> 
</video>

Of course as the article points out, prefixed versions are needed and the media query can be tweaked even further to provide high-res but smaller dimensioned videos to device with different screen sizes. A more complete example, using vendor prefixes, might look something like this:

<video controls> 
   <source type='video/mp4' src='video-high-res.mp4' media='(min-device-pixel-ratio:2), (-webkit-min-device-pixel-ratio:2), (min--moz-device-pixel-ratio:2), (-o-min-device-pixel-ratio:2)'>
   <source type='video/webm' src='video-high-res.webm' media='(min-device-pixel-ratio:2), (-webkit-min-device-pixel-ratio:2), (min--moz-device-pixel-ratio:2), (-o-min-device-pixel-ratio:2)'>
   <source type='video/mp4' src='video.mp4'>
   <source type='video/webm' src='video.webm'>
</video>

Except it doesn’t actually work.

The devices I tested on always fell through to the source element that didn’t have any media query set. Removing the source that had no media query set caused the “retina” source to play fine, so the media query value itself wasn’t what was causing it to be skipped, it just appeared to favour the source that had no media query.

So I decided to set the media attribute on the other source element, and to use max-device-pixel-ratio (and its prefixed versions), set to a value of 1:

<video controls> 
   <source type='video/mp4' src='video-high-res.mp4' media='(min-device-pixel-ratio:2), (-webkit-min-device-pixel-ratio:2), (min--moz-device-pixel-ratio:2), (-o-min-device-pixel-ratio:2)'>
   <source type='video/webm' src='video-high-res.webm' media='(min-device-pixel-ratio:2), (-webkit-min-device-pixel-ratio:2), (min--moz-device-pixel-ratio:2), (-o-min-device-pixel-ratio:2)'>
   <source type='video/mp4' src='video.mp4' media='(max-device-pixel-ratio:1), (-webkit-max-device-pixel-ratio:1), (max--moz-device-pixel-ratio:1), (-o-max-device-pixel-ratio:1)'>
   <source type='video/webm' src='video.webm' media='(max-device-pixel-ratio:1), (-webkit-max-device-pixel-ratio:1), (max--moz-device-pixel-ratio:1), (-o-max-device-pixel-ratio:1)'>
</video>

It was this combination (not strenously tested!) that actually worked.

Yet another use for the media attribute and another reason why it should stay around!