Making Parallaxed HTML5 Video Work

Mar 23, 2022

A staple of modern, trendy web design is the parallaxed, scrolling image. You know the one; where a background image is seemingly revealed by a transparent block, staying fixed relative to the viewport. as you scroll down a document.

Check out an example.

This effect became easily accomplished in pure CSS with the widespread adoption of the background-attachment:fixed; property. Just create a block, any block, fix the background to the viewport and it's done!

With a little javascript, moving the image fractionally up and down with the global document scroll can create an even fancier effect, but we'll leave that for another time. :)

So, images can be easily parallaxed, but what about videos? Background videos have been a thing for a while haven't they? Why shouldn't a parallaxed version be just as easy as an image?

Well... the thing is, background videos on HTML pages aren't really "backgrounds" in the CSS sense. They are <video> elements positioned behind other elements so they simply appear to be a background. In actuality, they must be somewhere in the flow of the document, and this is an important issue to note!

CSS backgrounds can be "fixed" to the viewport with background-attachment:fixed; but they remain backgrounds, fully contained by their parent element. However, when you fix a <video> element to the viewport with position:fixed; it automatically gets promoted to a CSS z-index above all other elements. This is a problem because you want the video to be visible only within, and contained by, the "transparent" block that scrolls up and down with the document. Since using position:fixed; takes the <video> out of the normal document flow, the CSS overflow:hidden; on the parent element has no effect!

Even if you try to hide a fixed position <video> element with other elements before and after it in the document flow by giving them a higher z-index value, the video will still "spill out" of the document wherever there are normal elements with no z-index assigned. In fact, you will need to z-index and background-color all the basic blocks of your document so that nothing can peek through in order for a fixed position <video> to work as a parallax video.

Check out an example of this problem.

To be truly reusable, a solution needs to be self-contained and drop-in ready, without the need to edit any other elements in your document. Can we do this?

It turns out, by abandoning position:fixed;, but adding a little bit of Javascript to mimic it, we can. The key is a method called getBoundingClientRect() which returns the position of any element relative to the viewport.

By using these coordinates of the parent element, and triggered by the scroll event on the window, we can dynamically re-position a child <video> element using position:absolute; instead of fixed. This allows the CSS property overflow:hidden; on the parent element to correctly hide the parts of the video we want hidden as the user scrolls the document.

See the code and example here.

The effect is not 100% perfect. On slower machines, or if you scroll-wheel up and down really fast, you may see the video bounce around a bit, but it works well enough that in most situations it will go entirely unnoticed. And if for some reason Javascript has been disabled in the user's browser, the video will still be there playing, but just statically scroll along with the document instead.

Give it a try and let me know how it works for you. :)


Comments closed

Recent posts

  1. Customize Clipboard Content on Copy: Caveats Dec 2023
  2. Orcinus Site Search now available on Github Apr 2023
  3. Looking for Orca Search 3.0 Beta Testers! Apr 2023
  4. Simple Wheel / Tire Size Calculator Feb 2023
  5. Dr. Presto - Now with MUSIC! Jan 2023
  6. Archive