Properly handling HTML5 video

By Michael Argentini
Managing Partner, Technology and Design

There's a common website homepage layout pattern that's en vogue right now, whereby the navigation, primary message (hero), and tentpole services or products lead the way. Our site currently follows this pattern, unapologetically. It's comfortable for visitors, making it easy to find the information in which they're interested. Pages with this layout tend to start like this:

Logo
Navigation
Hero
Item 1
Item 2
Item 3
Item 4

 
As a commonly used layout, it can require a unique spin to make it your own. And one of the strategies to satisfy this need is the use of subtle background video in the hero area. The irony here is that as people adopt similar strategies, the uniqueness wanes. So when we adopted the layout, we chose to separate ourselves in a more subtle way; aside from the messaging itself.

Video Handling

We took a look at how sites generally handle video in this way, and we became keenly aware that these implementation strategies yielded some areas for improvement:

  • Choice of video
  • Mobile and autoplay
  • Device energy consumption
  • Video formats

Choice

It was immediately apparent that choosing a video was about more than the metaphor it represented. Our desire was to use a modern device interaction as the video subject; preferably a tablet. But we wanted to be sure that:

  • it was subtle, ambient, and didn't distract visitors from our message (an overlay atop the video),
  • it had slow movement,
  • it provided visual interest, but only in support of the message,
  • it wasn't too busy, with too many distracting subjects,
  • audio was excluded, or if used, ambient in nature,
  • and the message overlay was completely legible.

Bad Choice

Too busy, too much movement, text overlay would be hard to read.

Good Choice

Subtle movement, few subjects and objects, text overlay would be easy to read.

Mobile and Autoplay

Mobile devices like Apple iPhone and iPad will not autoplay a video, and will default to showing a playback control. And since a mobile device is often using data plan bandwidth, video should be used only when it has great value. So we decided to use a still frame from the video in place of the video on these devices. This meant that we had to include programming logic to handle the switch based on the page width.

Device Energy Consumption

When video plays it causes the device to consume more energy. And with so many people using phones, tablets, and laptops, you need to be conscious of this fact, and considerate in your use of their batteries. To that end, we used additional programming logic to detect when the site is in the background, and pause the video. The OS X Activity Monitor bears this out as you can see below.

Video Playing...

Safari's energy use spiked at 65 (above).

Video Paused...

Safari's energy use settled in at 1.3 (above).

Apple has been cagey when it comes to defining exactly what this measurement is, but Apple engineers described it as a number that is a relative measure of the energy impact of an app or process, taking into account factors such as overall CPU utilization, idle energy draw, and interrupts or timers that cause the CPU to wake up. Regardless, video playback in this case represents a 50x increase in energy usage over a still image.

Video Formats

We generally recommend supporting a pragmatic list of operating systems and browser platforms. And many of them prefer different video formats. And some video formats produce better output than others. So we generally follow this priority list of video formats:

  1. H.264 (.m4v, .mp4 files); Apple Safari, Microsoft IE 9+, Google Chrome 31+, Mozilla Firefox 38+
  2. WebM (.webm files); older Google Chrome, Mozilla Firefox
  3. Ogg/Theora (.ogv files); older Mozilla Firefox versions

Example

I'm not going to get into the styling (CSS) of the video area (or the swapping of the still image for mobile), but do wish to cover the dynamic video implementation. In that spirit, let's start with the following HTML5 video tag:

<video autoplay loop class="video" poster="images/videos/home-tablet-2.jpg" id="herovideo"></video>

Notice there are no <source>tags. We set the video to autoplayand loop, and specify a static background to render while the video is loading. We only want to load the video if it's being viewed on desktop, which for us is at 1025 pixels in width or larger (since iPad in landscape is 1024 pixels wide).

Note: we approach responsive layouts using breakpoints based on content, not specific devices. But we have to be pragmatic, so considering the majority of popular devices is always in play.

So let's add some JavaScript code after the <video>tag to load the <source>tags if viewed on a desktop class device.

<script type="text/javascript">

    $(document).ready(function() {

        var breakpoint = 1024;

        loadVideo();

        // Pause when page is not in the foreground
        $(window).blur(function() {
            $('#herovideo')[0].pause();
        });

        // Play when page returns to the foreground
        $(window).focus(function() {
            if ($(document).width() > breakpoint) {
                $('#herovideo')[0].play();
            }
        });

        // Play video when page resizes
        $(window).resize(function() {
            loadVideo();
        });

        // Play when page returns from browser history button
        window.onpopstate = function() {
            if ($(document).width() > breakpoint) {
                $('#herovideo')[0].play();
            }
        };

        function loadVideo() {
            var video = document.getElementById('herovideo');

            // Remove existing source tags for mobile
            if ($(document).width() < breakpoint + 1) {
                while (video.firstChild) {
                    video.removeChild(video.firstChild);
                }
            }

            // Add source tags if not already present
            if ($(document).width() > breakpoint) {
                if (document.querySelectorAll("#herovideo > source").length < 1) {
                    var source1 = document.createElement('source');
                    var source2 = document.createElement('source');
                    var source3 = document.createElement('source');

                    source1.setAttribute('src', '/tablet.mp4');
                    source1.setAttribute('type', 'video/mp4');

                    source2.setAttribute('src', '/tablet.webm');
                    source2.setAttribute('type', 'video/webm');

                    source3.setAttribute('src', '/tablet.ogv');
                    source3.setAttribute('type', 'video/ogg');

                    video.appendChild(source1);
                    video.appendChild(source2);
                    video.appendChild(source3);
                }

                // Play the video
                $('#herovideo')[0].play();
            }
        }
    });
</script>

Here are some notes on the implementation:

  • We check the document (page) width, and only process video when we know the window is wide enough.
  • We check the document (page) width on resize events, return from browser history, and on focus.
  • We only load <source>tags when the document (page) is wide enough.
  • We only add the <source>tags when the document (page) is wide enough, and they are not already present.
  • Since the browser will ignore formats it doesn't handle, the first one will always be the preferred, best option, making playback as simple as calling child element zero.

The end result addresses all of the gaps we identified at the outset. The bandwidth and energy consumption handling can be checked by watching the network activity of the page load at different sizes. Mobile clearly has no awareness of a video file, while desktop loads and plays it seamlessly.

If you have the need, give this approach a go, and let us know how you make out. We'd love to hear your experience and comments.

Article last updated on 4/21/2018