I bet you’ve seen it. A video background that takes up the entire browser window. There is text on top of it (hence, “background”), which is an interesting effect that you don’t see every day. The biggest reason you don’t, probably, is that you can’t set a movie file as the background-image in CSS. You’ll have to do some layout trickery to get it done.

Certainly, full page background video can be just A BIT MUCH. I’d argue it can be done tastefully. I’m not particularly interested in a design philosophy debate here (perhaps another time), but instead the how-to of getting it done if you need to, as well as some different patterns it might take the form of.

It’s still worth mentioning the basics of tastefulness here:

  • No sound. At least by default. Opt-in sound is acceptable.
  • Respect bandwidth. Video is about the heaviest thing you can put on a website, and this is video that people didn’t exactly ask for, so mind that.
  • Keep it accessible. You’re probably putting text on top of the video, so make sure it has enough contrast to be readable.

Let’s do this thing Montana style, in honor of the trip Media Temple and I are taking to visit ZaneRay.

The How-To of Full Page Background Video

We’re in luck here. Dudley Story has already done a lot of research about this and has a nice setup we can use. He’s also got a demo page.

We need to put the video on the page, of course, so here’s that:

<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> 

There are a lot of attributes there! The poster attribute gives the video an image to show while the video is loading or in case the video doesn’t load at all. You might also want to use a background in CSS.

The autoplay attribute is there because we are wanting the video to automatically play. Remember we’re being tasteful here, so this is OK. There is no controls attribute, so there is no way for the user to start/stop the video. The playsinline attribute is so this works on iOS. The muted attribute is just in good taste (the video shouldn’t have audio anyway, but also, is requires on iOS to get the autoplay working. Then loop makes it, well, loop.

To cover the entire page with the video, you can do this:

video { object-fit: cover; width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; } 

That’ll get you full page video! Nice!

Now let’s look at some patterns. There is just one way to handle full page video, but there are a number of things we could do.

Just One Viewport

We’ve plopped the video into place. Now we can set whatever we want on top of it.

Take some text like this:

<header class="viewport-header"> <h1> Explore <span>Montana</span> </h1> </header> 

We can place that after the video and relative position it, so it appears on top. Then apply a little centering:

.viewport-header { position: relative; height: 100vh; text-align: center; display: flex; align-items: center; justify-content: center; } 

We have the simplest possible effect (see demo):

We could also position other things that we like anywhere on the page. It’s not particularly en vogue, but we could even drop an area of text that scrolls independently, such that the “full page” affect remains intact. (see demo)

The video can remain full screen, and have other elements scroll away. There is no reason the header needs to stay fixed! In this demo, the header text (which still fills the viewport exactly) scrolls away and the body copy comes up as you would expect. It’s even lightly transparent, showing the video behind still.

Here’s that demo:

The header text we placed over the video could remain fixed, and the content could slide up on top of it. One way to pull that off is to fixed position the video and header but still make sure the main content is pushed off the viewport, by using margin-top: 100vh; Here’s that demo:

Taking that a smidgen further, we could wire up some opacity and scale changes to scroll position and have the header text fade away into the background on scroll. Easily done with CSS custom properties! Here’s that demo.

One idea, lots of ways!