Photograph of Polina

Polina

filmed by Alexander Wagner 2011

fullscreen demo

This article is also available in French and Japanese

While we can’t yet set a video for the background or background-image properties – they can only take bitmaps, images, colors and gradients as values – it is possible to fake the appearance of a background video by forcing it behind other HTML elements. The challenge is to have the video fill the browser window, making it as responsive as background images.

Considerations and Limitations

Before achieving this, there some factors you should consider:

  • Don’t just use this technique because you can: video content must amplify a site’s message, not just be shown because it’s pretty.
  • The video will likely be set to autoplay, but it should be muted by default; ideally, it should not include sound at all. (You can easily create an unmute button for the video with JavaScript).
  • The video should display a placeholder image, falling back to a static background image for browsers that do not support HTML5. The placeholder image will also be used a background on mobile devices: many phones and tablets do not support autoplay, for obvious reasons.
  • Length is important: too short a video can feel repetitive (as most such videos will be set to loop), while too long becomes a narrative unto itself, and therefore deserving to be a separate design element. I’d suggest a run time of approximately 12 – 30 seconds.
  • is important: any text placed on top of the video should be in high contrast. Users should have easy access to a UI control to pause the video; ideally, the video should play through only once.
  • Bandwidth is a big deal. The video needs to be small, and compressed as effectively as possible. At the same time, it needs to scale across different devices and their associated screens. In advanced cases, you might want to consider using inline media queries or matchmedia to send different quality versions of the video to different screen sizes. Try to keep the video under 5mb; ideally, under 500k.

With these factors in mind, let’s look at techniques for making the video happen, using a piece shot by Alexander Wagner.

A Pure CSS Approach

Build the HTML5 video as usual:

<video playsinline autoplay muted loop poster="polina.jpg" id="bgvid">
    <source src="polina.webm" type="video/webm">
    <source src="polina.mp4" type="video/mp4">
</video>

Important: the order of the video files is vital; Chrome currently has a bug in which it will not autoplay a .webm video if it comes after anything else.

The poster image will be replaced by the first frame of the video once it loads, so it makes sense to derive that image from the same first frame.

To make the video fullscreen:

video#bgvid { 
    position: fixed;
    top: 50%;
    left: 50%;
    min-width: 100%;
    min-height: 100%;
    width: auto;
    height: auto;
    z-index: -100;
    -ms-transform: translateX(-50%) translateY(-50%);
    -moz-transform: translateX(-50%) translateY(-50%);
    -webkit-transform: translateX(-50%) translateY(-50%);
    transform: translateX(-50%) translateY(-50%);
    background: url(polina.jpg) no-repeat;
    background-size: cover; 
}

Older browsers will not recognize the video formats, but should still recognize the basic <video> tag (with the exception of IE8, detailed below). For those browsers we create a background-image for the element, using the same placeholder picture. At this stage only Safari (mobile and desktop) requires the -webkit vendor prefix for transforms, so it has been included in the code; if you're also targetting Firefox 15 or earlier, you'll want to include a -moz prefixed version of the transform.

Dealing With Mobile

Displaying the fullscreen background video on mobile devices presents several challenges:

  1. Many mobile platforms will refuse to autoplay HTML5 video to avoid potentially ruinous data charges (see exceptions below).
  2. In such cases the video will be displayed with an embedded play button, which in turn…
  3. …may capture touches on the device, locking out links that may be in the content on top of the video.

While it is possible to feature-detect support for video autoplay with JavaScript (a technique I will cover in a future article), the easiest solution is to use a media query that switches off the video entirely on smaller screens, substituting the placeholder image in the background. To the existing CSS, add:

@media screen and (max-device-width: 800px) {
    html {
         background: url(polina.jpg) #000 no-repeat center center fixed;
    }
    #bgvid {
        display: none;
    }
}

The media query itself is the most important part, and will need to be modified based upon both the expectations of the site and a changing mobile space. Currently, it detects if the display screen is physically less than 800 pixels wide, and if so switches the video for a static background image. Note that this ignores Retina: an iPad 3 will still register a horizontal resolution of 768px under this media query, even though its actual resolution is far higher.

Integrating Accessibility

Users with vestibular disorders can become motion-disoriented, especially when trying to read text in front of a moving image, while users on the autism spectrum can be disturbed by rapid change. For those users - and everyone else - a pause button should be within easy reach:

<button id="vidpause">Pause</button>

For users with browsers that have a Prefers Reduced Motion accessibilty setting (currently Safari 10.1), we can add the following script to the bottom of the page:


var vid = document.getElementById("bgvid"),
pauseButton = document.getElementById("vidpause");
if (window.matchMedia('(prefers-reduced-motion)').matches) {
    vid.removeAttribute("autoplay");
    vid.pause();
    pauseButton.innerHTML = "Paused";
}

This will set the video to paused by default for those users.

Ideally, the video should also stop and fade out when it has played through once. Add the following to the script:


function vidFade() {
    vid.classList.add("stopfade");
}
vid.addEventListener('ended', function() {
    // only functional if "loop" is removed 
     vid.pause();
	// to capture IE10
	vidFade();
});
pauseButton.addEventListener("click", function() {
    vid.classList.toggle("stopfade");
	if (vid.paused) {
vid.play();
		pauseButton.innerHTML = "Pause";
	} else {
        vid.pause();
        pauseButton.innerHTML = "Paused";
	}
})

The JavaScript calls on some CSS added to your stylesheet (with vendor prefixes removed for clarity):

video#bgvid {
    transition: 1s opacity;
}
.stopfade { opacity: .5; }

(Of course, you should also write CSS to make the button element disappear on mobile devices, given the solution above: otherwise, the button will appear on iPhones with iOS 9 or lower without any apparent purpose).

Pure JavaScript Alternatives

While I would argue that a HTML5 / CSS solution is better than a framework, there’s at least one JQuery plugin that creates similar results to what is shown here.

Conclusion

“Background” video can be a very powerful feature on a site, but with great power comes great responsibility: please use such features judiciously.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/knqyK