@spub_editor

A moving background makes a landing page feel alive — product shots drifting behind the headline, ambient footage setting the mood. Done right, it's modern design. Done wrong, it's a 40 MB file blocking first paint on phones. Here's the complete recipe: the HTML, the autoplay rules, the file prep, and the performance guardrails.

The basic pattern

The modern way is a `<video>` element layered behind content — not a CSS background (CSS can't hold video natively):

```html <section class="hero"> <video class="hero-bg" autoplay muted loop playsinline poster="hero-poster.jpg"> <source src="hero.webm" type="video/webm"> <source src="hero.mp4" type="video/mp4"> </video> <div class="hero-content"> <h1>Your Headline</h1> </div> </section> ```

```css .hero { position: relative; overflow: hidden; } .hero-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; } .hero-content { position: relative; z-index: 1; } ```

Every attribute in that video tag earns its place — read on.

The four attributes that make autoplay work

Browsers block autoplay to protect users from surprise sound. The unlock conditions:

1. **`muted`** — the big one. Muted videos may autoplay everywhere; unmuted ones cannot, full stop. 2. **`playsinline`** — stops iOS Safari from going fullscreen; without it, iPhone autoplay dies. 3. **`autoplay`** — starts playback when possible. 4. **`loop`** — background video runs forever; see our looping guide for what the attribute does.

`poster` shows while the video loads — your visual holding pattern. Skip the attribute and users see a black flash.

Preparing the file: size is design

A background video is decoration; treat its bytes like an image budget:

- **Duration 6-12 seconds**, seamlessly looped — nobody watches 60 seconds of background - **Resolution 1280×720 or less** — it sits behind a dark overlay and content; 4K detail is invisible - **Bitrate 1-2 Mbps** — motion stays smooth, gradients stay clean - **H.264 MP4 + VP9/WebM pair** — MP4 everywhere, WebM smaller where supported (order matters: list WebM first)

```bash ffmpeg -i raw.mp4 -vf "scale=1280:-2,fps=24" -c:v libx264 -crf 28 \ -an -movflags +faststart hero.mp4 ```

`-an` drops audio entirely (it's muted anyway — dead bytes), `+faststart` lets playback begin before the download finishes. A 10-second result lands around 2-4 MB. That's the target.

The mobile question

Consider swapping the video for the poster image on small screens or metered connections — same mood, zero cost:

```css @media (max-width: 768px) { .hero-bg { display: none; } } ```

Or gate it with `navigator.connection.saveData` in a few lines of JS. Desktop gets cinema; phones get speed.

Accessibility: the rules that aren't optional

- **`prefers-reduced-motion`**: users who opt out of animation must get the static poster — respect it:

```css @media (prefers-reduced-motion: reduce) { .hero-bg { display: none; } } ```

- **Never put essential content only in the video** — screen readers and search engines can't watch it. The headline exists as text. - Contrast: a dark overlay between video and text keeps copy readable as footage shifts.

The performance checklist

- File ≤ 4 MB after the encode above - `poster` always set - Video `preload="metadata"` or none — don't download before needed: add `preload="none"` and let autoplay trigger it - Lazy-mount below-the-fold heroes with IntersectionObserver - Lighthouse check: the video shouldn't shift LCP; poster and content paint first

The takeaway

`autoplay muted loop playsinline` + poster, 720p at ~2 Mbps, 8-second loop, mobile fallback, reduced-motion respect. The video is the garnish — the page's job is still to load fast and read clearly with the video switched off.

📹 Have a video or photos to share?
Upload to S.pub and get an instant share link — free, works everywhere, no watermarks.
Upload your video →
Comments 0

No comments yet