Adding Ambient Video Backgrounds to Websites

March 11, 2015
Design, Footer

Update 6/23/20 – The post below explains the technical implementation of ambient videos. We recently published another post, Examples of Ambient Videos on Websites, that runs through our favorite ways to use them online. Check out both, or read the one that interests you the most!

In his January post Web Design & Development Trends You'll See in 2015, our own Nathan Huening included Ambient Video as one of the big trends to watch this year.

Used to be that to play a video in a browser, you had to have a Flash plugin. With the rise of browsers that support both the HTML5 <video> tag and H.264 format, they'll run on their own and can be manipulated like any other page element. What to do with this new-found ability? Why, auto-play video in the background! Who needs a big static hero image when you can have a big attention-grabbing one?

So far, that has proven to be true.  We've not only seen these videos popping up around the web for brands of all sizes, but we've also been incorporating ambient videos into more of our projects.  How do we use this technology? Glad you asked.

Sources of Video

First, we have to have a video available for use in the project. This could be provided by the client or found on a stock video site. Options for stock video are abundant, but DissolveShutterstock, and iStock are great places to start. The source itself doesn't matter from a technical standpoint, just ensure that you have legal rights to use the video. Also, make sure the video works well without sound because you're not going to autoplay sound on your website, right? Nobody likes to arrive to a website and have sound autoplay if they didn't choose to play. If you don't believe me, here are 5 good reasons not to play sound on your website. Thank you Google.

The format of the video matters too, because you want as many users as possible to be able see it. In the past, this was much more painful with HTML5 video because you needed to use multiple formats to ensure good browser coverage. Now, you can get by with MP4 as it's widely supported. IE8 and Opera Mini support is not a factor since neither support the <video> element. If you really want to provide other options there's no harm in doing so, but it may not be necessary.

Compression Thoughts

Once we have the video in the proper format, we then have to determine what is an appropriate file size. This is a great article explaining this concept in-depth, but the general idea can be summarized with this equation: Filesize = Bitrate x Duration. Let's say you have a 30mbps connection, meaning you can download up to 30,000KB per second of data. For the video to stream without having to buffer, the video can't require more than 30,000KB/s per second to download. You can and probably should reduce your target to account for times when users don't actually achieve their maximum speeds, maybe 20,000KB/s or less.

To find out how many kbps your video will require, simply divide the filesize by the duration. If you have a 30 second video that has a file size of 20mb then we can plug that into our equation: 20MB / 30 seconds = 0.67MB/s, or 670KB/s. This is our bitrate, and is far less than our capability of 20,000KB/s, so we should be in good shape. Always encode at a bitrate lower than your target user's connection speed, since traffic and bandwidth can greatly reduce actual connection speed.

Responsive

One big advantage we gain by using the HTML5 <video> element is that it can be styled just like any other block-level element so it is easy to make it responsive. The container can just scale as if it were an <img> tag.

Graceful Degredation

A nice thing about ambient video is that as a fallback; an image makes for an excellent replacement. If we show an image instead of a video, the experience still works for a visitor. In the the example below, we're using HTML, CSS, and JS to detect whether or not to apply the video (based on width, browser, and device), and then either apply the video or fall back to an image. We like to send an image to older browsers or mobile users (since they are more concerned with bandwidth and performance). Let's start with the markup.

The Markup

We have a container with an inner element containing several data attributes that our JS will utilize.

<section id="big-video">
    <div class="video" data-src="[FALLBACK IMAGE URL]" data-video="[VIDEO URL]" data-placeholder="[PLACEHOLDER IMAGE URL]"></div>
</section>

Essentially we are establishing a couple of containers and adding the relevant information into data- attributes that javascript can read. Notice that we are including two different images. If we are going to show a video, we want to use the first frame of the video as a placeholder — this is specified by the data-placeholder attribute. This may show for a few moments while the video buffers. Using the first frame ensures that the transition from placeholder to video is smooth.  If we are showing an image, it makes more sense to editorially select a replacement (with data-src) since a first frame can sometimes be out of place.

Scripts

First, we are doing some device and browser testing. Then, if all requirements are met, we're adding the video element to our inner container. If the requirements are not met we're adding a div with a background image set.

function isIE () {
    var myNav = navigator.userAgent.toLowerCase();
    return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
}

window.isIEOld = isIE() && isIE() < 9;
window.isiPad = navigator.userAgent.match(/iPad/i);

var img = $('.video').data('placeholder'),
    video = $('.video').data('video'),
    noVideo = $('.video').data('src'),
    el = '';

if($(window).width() > 599 && !isIEOld && !isiPad) {
    el +=   '<video autoplay loop poster="' + img + '">';
    el +=       '<source src="' + video + '" type="video/mp4">';
    el +=   '</video>';
} else {
    el = '<div class="video-element" style="background-image: url(' + noVideo + ')"></div>';
}

$('.video').prepend(el);

This code first runs a few tests to determine whether to show a video based on browser, window resolution and whether or not the device is an iPad. You can use whatever tests you like.  The rest of the code uses the data attributes to drop in the appropriate markup depending on the situation.

CSS

All that is left is to style the remaining markup. One small performance trick we like to use is to set the size of the container using CSS rather than letting it scale from either the <img> or <video> tag. This lets the browser draw the page before either element loads. Otherwise it would need to wait for those elements to load to know the dimensions of the container.

 We want the video to maintain the size of the outer element, so we're using a trick to make the height scale with the width while maintaining aspect ratio. Because a height property set to a percentage value will try to use the height of parent elements to get the value, we need to take a different approach. When padding is set to a percentage, that percentage references the width of the element. If we know the height/width ratio, we can set the height of the element to zero and the top or bottom padding to that ratio. Then position the video element absolutely to fill the entire container, resulting in a video that scales proportionately. We also have styled the fallback image in a similar way.

#big-video {
    position: relative;
    background: #000;
    overflow: hidden;
    height: 582px;
}

#big-video .video {
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 0;
    padding-bottom: 56.25%;
}

#big-video video {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
}

#big-video .video-element {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    background-size: auto 100%;
}

Conclusion & Examples

So, it's as easy as that!  Follow those steps and you can add this functionality to your site and make sure it performs well for all of your visitors.  If you have any other tips or thoughts, feel free to leave them in the comments.  Here are a couple of examples where we've used this approach on recent projects.

Comments

Echo's avatar
Echo
This doesn't work anymore. The images take over and there's no video. The images don't even go full height or full width. Not sure why this doesn't work. Great job though.
Chris's avatar
Chris
Hi Todd,
This looks really useful. What would be helpful for us novices is if you told us where to place each of these code segments. What files am I editing?

Thanks again for your skills and for sharing!

Chirs
Zlatko's avatar
Zlatko
hi and thanks for your help

so if you are not a coder like me and use a theme done by coders where exactly and how exactly would you do that. pleas if some one some how can explain the whole way for people do even not know . i would like to add a video in the login and register page as a background. the others i have a plugin but no one in the www explain it really slowly and shorley

when i add the code of function in my function php it shows red wrongs, the first code i even don't know where.
the css is maybe in the costume.css

thanks to every one who can help

Mutch respect to real coders that is awesome work to understand everything .-)
handyman san francisco ca's avatar
handyman san francisco ca
Helpful information. Fortunate me I found your
website unintentionally, and I am stunned why this accident didn't took place earlier!

I bookmarked it.
Kyle's avatar
Kyle
Good write-ups, I've used similar methods in the past. There's also some ready made scripts out there such as BigVideo.js.

Any reason you're not detecting the viewport and loading an appropriately sized video? I've seen some machines go to a crawl because they can't handle 1080p video, but they can handle 720p. Usually these machines are older and thus have lower resolutions, so it stands to reason that if the resolution is south of 1920x1080 and closer to 1366x768, it should get the smaller clip loaded versus the full-blown 1080p.


Also, to answer the question on the Retina display (comment up above). I wouldn't worry about it. You have to keep in mind that 1080p video looks fine on 32" monitors, and 720p is passable on 20". So gauge it by that, not by the pixel density (DPI). That just makes text sharp.
Austin Williams's avatar
Austin Williams
Derp.

Actually, we're both wrong. lol.

20MB /30 seconds = 0.67MB/s. That's 0.67 megaBYTES per second. Then we have to convert that to mbps (megaBITS per second).

0.67 MB/s = 5.36mbps. And then, finally, convert that to kbps...

5.36mbps = 5360 kbps

Much better than we thought. :D
Austin Williams's avatar
Austin Williams
Thank you for this article. It has been extremely useful!
:)

Quick correction:
"...then we can plug that into our equation: 30 seconds / 20mb = 1.5mbps ..." should say "...then we can plug that into our equation: 20mb /30 seconds = 0.67mbps ..."

To compute mbps you have to put the file size (in mb) in the numerator and the duration (in seconds) in the denominator.
Darren's avatar
Darren
I was wondering if this example worked on higher resolution viewports like retina screens?

For example, a retina Macbook Pro has a screen resolution of 2880x1800 but to record video at that resolution creates a massive file size, even compressed. I'm using climpchamp.com to reduce the file size (quality) but keep the resolution (pixel size) . I can always record new video at higher resolution but will we have to keep doing that as screen resolution size keeps increasing?

Is this why you tested for iPad in the scripts? I'm sorry if this is a basic question but I'm having trouble finding an answer even on stackexchange.
Tom Wilson's avatar
Tom Wilson
Hi

Thanks for the awesome article, I'm really keen to master this technique so I can build sites in a similar vein to 'Beyond the Beltway' - it's very impressive.

I am currently trying to add to a wordpress site I'm building here - http://roomswithstyle.com.au/melbmothers/gynaecology/
I have enqueued the script and can see it loading in the footer but for some reason the I end up with an undefined src -


If you could offer any insight on where I was going wrong I'd be much obliged.
Thanks again for the great snippets and indeed sharing them.

Cheers
Tom

Leave a comment