Front-End Case Study
How to Add Background Videos using HTML and CSS
Background videos instantly elevate the visual appeal of a website, adding dynamic motion that captures a visitor's attention the moment they land on your page. However, if you've ever tried to implement a hero background video, you've likely run into the dreaded "Safari Autoplay Gotcha."
Today, we're taking a break from our AI series to dive into a purely vanilla HTML and CSS implementation for background videos. This isn't your standard implementation, this is a bulletproof workaround designed specifically to conquer Safari's strict media playback rules.
Hero sections often require a premium appeal to increase user retention for above the fold content. Moving elements can be seen on the homepage of my portfolio.
To save battery and prevent annoying noisy ads, modern browsers have strict autoplay policies. Usually, adding autoplay, muted, and playsinline to your HTML <video> element is enough to get it running on Chrome and Firefox.
Safari (especially on iOS), however, plays by its own rules. Even with those attributes, Safari will often refuse to autoplay a <video> element without explicit user interaction, especially if the device is in Low Power Mode.
The Solution: A little known WebKit quirk. Safari natively supports rendering video files (like .mp4) directly inside the CSS background property! Chrome and Firefox generally ignore video files in CSS backgrounds, treating them as invalid images.
We can use this discrepancy to our advantage. By defining the video as a CSS background and using a standard <video> element behind the content using z-index, we create a flawless cross-browser experience. Safari gets its CSS background video, and other browsers fall back to the DOM-dominant <video> element.
Let's break down how to build this step-by-step.
First, we need to set up our hero section. We'll create a container that holds our text content and our <video> element.
<header id="home" class="bg-image-hero position-relative"><div class="container hero-content"><div class="row"><div class="col-12" style="padding-top:70px;"></div><div class="col-md-7 col-lg-6"><p class="h5 fw-light mb-3">Hi there, I'm a Hero Section</p><h1 class="display-2 mb-4">Modern<span class="text-primary">Web</span>Developer</h1><p class="h4 fw-light mb-5">Some Hero Text</p><a href="#portfolio" class="btn btn-primary btn-lg rounded-pill px-5 py-3 shadow-lg">View Recent Work</a></div></div></div><!-- The Standard Video Element --><video autoplay muted loop playsinline id="background-video"><source src="/img/as_background_vid.mp4" type="video/mp4" />Your browser does not support the video tag.</video></header>
What's happening here?
.bg-image-hero, which will act as our CSS background anchor.<video> tag includes the holy trinity of autoplay attributes: autoplay, muted, and playsinline.#background-video so we can target it easily with CSS.
Now for the secret sauce. We need to style the container to use the .mp4 as a background, and push the HTML <video> element behind the content.
<style>/* 1. The Safari Workaround Container */ .bg-image-hero { /* Safari native video background support! */ background: url("/img/as_background_vid.mp4") no-repeat 521px center/115%; background-color: transparent; height: 91vh; display: flex; align-items: flex-start; color: #fff; position: relative; max-height: 725px; overflow: hidden; } /* 2. The Standard Browser Video Element */ #background-video { position: absolute; left: 40%; bottom: -137px; min-width: 100%; min-height: 100%; z-index: -1; /* Pushes the video behind your text content */ object-fit: cover; /* Ensures the video fills the space nicely */ }</style>
1. .bg-image-hero: We declare the .mp4 file inside the url() of the background property. Safari will read this and render the video as a background. Other browsers will fail to load it as an image, leaving the container transparent.
2. #background-video: We use position: absolute and z-index: -1 to tuck the actual HTML <video> element underneath the text. On Chrome/Firefox, this is what the user sees through the transparent background of the .bg-image-hero container.
Finally, because we are using absolute positioning and specific background sizing, we need to adjust our layout for mobile and tablet screens to ensure the video stays centered and covers the area properly.
<style>/* Tablet Adjustments */ @media (max-width: 991.98px) { .bg-image-hero { background: url("/img/as_background_vid.mp4") no-repeat 332px center/1680px; } } /* Mobile Adjustments */ @media (max-width: 767px) { .bg-image-hero { background: url("/img/as_background_vid.mp4") no-repeat -450px 313px/1360px; background-color: transparent; max-height: 750px; } #background-video { left: 0; bottom: -337px; width: -webkit-fill-available; /* Safari specific fill property */ } }</style>
By tweaking the background position/size for Safari, and the left/bottom properties for the <video> element on other browsers, we guarantee that the focal point of your background video remains in view no matter what device your user is on.
Implementing background videos doesn't have to require heavy JavaScript libraries or complex intersection observers just to bypass browser policies. By understanding browser quirks—like Safari's willingness to render an MP4 in a CSS background property—you can build robust, fast, and vanilla solutions that work flawlessly across the board.