How to Use a Video Background in a Next.js Hero Section
Learn how to implement, optimize, and test responsive hero video backgrounds using modern HTML/CSS and Next.js, including accessibility and performance best practices.

Try it directly in Shufaf
No signup required to preview
Implementing a video background in your website's hero section can create an immediate visual impact. However, done incorrectly, it can degrade page performance, destroy mobile user experience, and violate accessibility standards.
This guide covers how to write production-ready video hero code, optimize assets for performance, maintain accessibility, and handle mobile edge cases.
Technical Implementation: Pure HTML & CSS
To create a video background, place a native <video> element behind your foreground content using absolute positioning.
HTML Structure
<section className="hero-container">
<video
autoPlay
muted
loop
playsInline
preload="metadata"
poster="/images/hero-poster.webp"
aria-hidden="true"
className="hero-video"
>
<source src="/videos/hero.webm" type="video/webm" />
<source src="/videos/hero.mp4" type="video/mp4" />
<!-- Fallback for browsers that don't support the video element -->
<img src="/images/hero-poster.webp" alt="Background fallback visual" />
</video>
<div className="hero-overlay"></div>
<div className="hero-content">
<h1>Automate Your Workflow</h1>
<p>Build faster with pre-configured pipeline assets.</p>
<a href="/docs" className="cta-button">Get Started</a>
</div>
</section>
Video Attribute Breakdown
autoPlay: Begins playback automatically. Most modern browsers will block unmuted autoplay.muted: Silences audio output. Required forautoPlayto function across mobile and desktop browsers.loop: Replays the video infinitely upon reaching the end.playsInline: Prevents iOS Safari from automatically opening the video in full-screen media player mode on mobile.preload="metadata": Tells the browser to download only video metadata initially, reducing bandwidth consumption during the initial render.poster: Defines a static image shown while the video streams or if video playback fails/is disabled.aria-hidden="true": Hides purely decorative video content from screen readers.
CSS Styling
.hero-container {
position: relative;
width: 100%;
min-height: 80vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.hero-video {
position: absolute;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translate(-50%, -50%);
object-fit: cover;
z-index: 0;
}
/* Semi-transparent overlay to guarantee text legibility */
.hero-overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.45);
z-index: 1;
}
.hero-content {
position: relative;
z-index: 2;
color: #ffffff;
text-align: center;
}
Next.js Implementation
In a Next.js (App Router or Pages Router) environment, you can encapsulate this logic into a reusable Server Component.
import Image from 'next/image';
interface HeroSectionProps {
title: string;
subtitle: string;
videoWebm: string;
videoMp4: string;
posterSrc: string;
}
export function HeroSection({
title,
subtitle,
videoWebm,
videoMp4,
posterSrc,
}: HeroSectionProps) {
return (
<section className="relative w-full min-h-[80vh] flex items-center justify-center overflow-hidden">
{/* Background Video */}
<video
autoPlay
muted
loop
playsInline
preload="metadata"
poster={posterSrc}
aria-hidden="true"
className="absolute top-1/2 left-1/2 min-w-full min-h-full w-auto h-auto -translate-x-1/2 -translate-y-1/2 object-cover z-0"
>
<source src={videoWebm} type="video/webm" />
<source src={videoMp4} type="video/mp4" />
<Image alt="Hero background fallback" className="object-cover" fill priority src="{posterSrc}"/>
</video>
{/* Dark overlay for contrast */}
<div className="absolute inset-0 bg-black/50 z-[1]" />
{/* Content Container */}
<div className="relative z-[2] text-center text-white px-4 max-w-4xl">
<h1 className="text-4xl sm:text-6xl font-bold tracking-tight">{title}</h1>
<p className="mt-4 text-lg sm:text-xl text-gray-200">{subtitle}</p>
</div>
</section>
);
}
Accessibility & Motion Preferences
For users sensitive to motion, continuous video loops can trigger vestibular disorders or motion sickness. Respect the user's OS-level accessibility setting using the prefers-reduced-motion media query.
CSS Solution
Hide the video and show a static background image when reduced motion is preferred:
@media (prefers-reduced-motion: reduce) {
.hero-video {
display: none;
}
.hero-container {
background-image: url('/images/hero-poster.webp');
background-size: cover;
background-position: center;
}
}
Contrast and Readability
Never display light text directly over raw video without an explicit contrast layer. Video frames shift continuously, making static text unreadable across varying light levels.
To maintain WCAG AA contrast compliance:
- Apply a solid or gradient overlay using
rgba()orbackdrop-filter. - Apply
filter: blur(2px)to the background video to soften visual clutter.
Performance & Optimization Guidelines
Large video files destroy Core Web Vitals, specifically Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS).
Target Video Specifications
- Format: Supply both WebM (modern, higher compression) and MP4 (universal compatibility).
- Resolution: Cap video resolution at 1080p (1920x1080). 4K backgrounds consume unnecessary bandwidth.
- Frame Rate: Export at 24fps or 30fps. 60fps files double the file size without noticeable UI benefits.
- Audio Track: Strip audio channels completely during export to reduce payload size.
- Target File Size: Keep the total video size under 5 MB (ideally 1–3 MB).
FFmpeg Compression Command
Run this terminal command to re-encode an MP4 video, strip audio, and optimize it for web streaming:
ffmpeg -i input.mp4 -vcodec libx264 -crf 28 -an -preset slow -movflags +faststart output.mp4
-an: Removes all audio tracks.-crf 28: Controls quality (higher values mean more compression; 23–28 is ideal for web background videos).-movflags +faststart: Moves metadata to the beginning of the file so video playback begins before full download.
When to Avoid Hero Video Backgrounds
Video backgrounds are not universally suitable. Consider alternative hero designs if:
- Mobile-First Audience: High data usage and cellular latency can cause video buffering on mobile connections.
- Data Density: If your hero section requires complex forms, multiple CTAs, or interactive tables, a background video creates excessive visual competition.
- Low Contrast Branding: Brand identity guidelines with soft pastel typography can be difficult to make readable over moving video layers.
Hero Background Trade-offs
| Background Strategy | Advantages | Disadvantages |
|---|---|---|
| Static Image | Fastest LCP, predictable contrast, zero motion friction | Lower visual dynamics |
| Video Background | Rich visual narrative, high immediate engagement | Higher payload (1–5MB), potential mobile battery/data impact |
| CSS Gradient / Animated Vectors | Minimal payload (< 10KB), hardware accelerated | Limited to geometric or procedural visuals |
Rapid Visual Testing with Shufaf
Before coding your video hero layout, you can instantly test video options, background opacity, and blur parameters using the Shufaf Studio Playground.
Instead of tweaking CSS rules and re-deploying local builds:
- Drop Your Assets: Drag your product mockups, typography, or UI screenshots into Shufaf Studio.
- Attach Video Clips: Test raw MP4/WebM files as live looping backdrops.
- Adjust Parameters: Use interactive sliders to dial in optimal Opacity and Blur values to ensure your foreground text remains fully visible before writing any layout code.