TL;DR
A hero background video looks premium in Figma — in mobile Lighthouse LCP often jumps above 4 s because <video autoplay> competes with poster image, fonts, and analytics for first paint. The LCP element may be a video frame, poster, or adjacent heading — you must measure, not guess. Production approach: WebP/AVIF poster as LCP, video with preload="none" or loaded after requestIdleCallback, on mobile static hero instead of video. Hosting on DevStudioIT Cloud with CDN does not fix an 8 MB MP4 — asset optimization and conditional rendering in Next.js do. Below: design/dev decision, component code, and thresholds for when to use video hero at all.
Who is this for
- B2B corporate sites with a brief saying "we want background video like Apple"
- Teams with LCP > 2.5 s after adding hero video in the last sprint
- Marketing measuring Google Ads conversions — slow landing raises CPC
- Next.js developers seeking compromise without rejecting video entirely
- Projects after redesign where CrUX dropped after swapping static hero for MP4
Keyword
video hero lcp, corporate site video performance, poster video nextjs, lazy load hero video, largest contentful paint video, autoplay background performance 2026
Why video hero dominates LCP
LCP measures time until the largest viewport element renders. With full-screen <video>:
| LCP candidate | Typical time (mobile 4G) | Problem |
|---|---|---|
| First video frame (no poster) | 3–6 s | Decoder + MP4 fragment download |
Poster <video poster="..."> |
1.5–3 s | OK if poster optimized |
| H1 beside video | 1.2–2 s | Video should not be LCP |
| Static hero image | 0.8–1.8 s | Benchmark for corporate sites |
Background autoplay requires muted, playsinline, loop — the browser still downloads the start of the file before the first frame is ready. A 5 MB MP4 exceeds the entire JS budget of a landing page.
Poster first — LCP-safe pattern
// components/HeroVideo.tsx
'use client';
import Image from 'next/image';
import { useEffect, useState } from 'react';
export function HeroVideo({ poster, src }: { poster: string; src: string }) {
const [showVideo, setShowVideo] = useState(false);
useEffect(() => {
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
if (mq.matches) return;
const idle = 'requestIdleCallback' in window
? (cb: () => void) => requestIdleCallback(cb, { timeout: 2000 })
: (cb: () => void) => setTimeout(cb, 1500);
idle(() => setShowVideo(true));
}, []);
return (
<div className="relative aspect-[16/9] min-h-[50vh] w-full overflow-hidden">
<Image
src={poster}
alt=""
fill
priority
sizes="100vw"
className="object-cover"
/>
{showVideo && (
<video
className="absolute inset-0 h-full w-full object-cover"
autoPlay
muted
loop
playsInline
preload="none"
poster={poster}
>
<source src={src} type="video/mp4" />
</video>
)}
</div>
);
}| Decision | LCP impact | UX |
|---|---|---|
Image priority on poster |
LCP ≈ poster | Instant visual |
preload="none" on video |
No bandwidth competition | Short delay before video starts |
| Video after idle | LCP already measured on poster | Acceptable on desktop |
prefers-reduced-motion |
Poster only | Accessibility + performance |
Mobile vs desktop — conditional hero
On mobile disable video — data savings and LCP:
import { headers } from 'next/headers';
export async function Hero() {
const ua = (await headers()).get('user-agent') ?? '';
const isMobile = /Mobile|Android/i.test(ua);
if (isMobile) {
return <HeroPosterOnly poster="/hero-poster.webp" />;
}
return <HeroVideo poster="/hero-poster.webp" src="/hero-loop.mp4" />;
}Alternative: CSS @media (max-width: 768px) hides <video>, but the file may still ship — server-side branch is safer.
| Breakpoint | Recommendation |
|---|---|
| < 768 px | Static AVIF poster |
| 768–1024 px | Short video ≤ 2 MB, 720p |
| > 1024 px | Loop 1080p ≤ 4 MB after optimization |
Video file optimization — not just lazy load
| Parameter | Target | Tool |
|---|---|---|
| Loop length | 5–12 s | Edit |
| File size | ≤ 2 MB mobile, ≤ 4 MB desktop | ffmpeg |
| Codec | H.264 baseline or H.265 with fallback | HandBrake, ffmpeg |
| Resolution | 1280×720 hero is enough | Scale in ffmpeg |
| Bitrate | 800–1200 kbps | -b:v 1000k |
ffmpeg -i raw-hero.mp4 -vf scale=1280:-2 -an -c:v libx264 -crf 28 -movflags +faststart hero-loop.mp4-movflags +faststart moves moov atom to start — faster first frames even when video is LCP (avoid that scenario).
Serve MP4 from DevStudioIT Cloud CDN with long Cache-Control — same origin as the page, no extra DNS to Vimeo/YouTube (iframe embed is a separate third-party problem).
Alternatives when video hero is ruled out
| Alternative | LCP | Visual effect |
|---|---|---|
| Short loop GIF replaced by MP4 | Medium | Better than 15 MB GIF |
| CSS gradient + subtle animation | Low | Modern, light |
| WebP sequence (sprite) | Low–medium | "Pseudo-video" 8–12 frames |
| Static hero + play button → modal | Low | Video on demand, not LCP |
| Light Rive / Lottie animation | Medium | Illustration instead of footage |
Brief "we must have video" — modal on click satisfies marketing without LCP penalty.
Measurement — confirm poster is LCP
- Lighthouse mobile → LCP section → element selector
- Chrome DevTools → Performance → Largest Contentful Paint marker
web-vitalswithreportAllChangeson staging
If LCP points to <video> — poster is not first paint (missing priority on Image or video loads before preload="none" takes effect).
Integration with performance budget
In Lighthouse CI assert LCP ≤ 2500 ms on /en with hero. PR adding <video autoplay> without poster-first should fail. Design review: video is its own budget category alongside JS and fonts.
Client brief — selling the compromise to marketing
Marketing often wants "background video" because competitors have it. Present numbers, not technical jargon:
| Argument | Data | Proposal |
|---|---|---|
| Slow LCP | +0.5 s ≈ 7–10% conversion drop (landing benchmarks) | Poster + video after idle |
| Mobile traffic | 60–70% B2B | Static hero on mobile |
| Production cost | 4K footage ≠ better loop | 720p 8 s is enough |
| Brand story | Video matters | Modal with full 30 s material |
Side-by-side Lighthouse demo: autoplay MP4 vs poster-first — same design, 2 s LCP difference convinces PO faster than a CWV slide.
Video hero accessibility
| Requirement | Implementation |
|---|---|
prefers-reduced-motion: reduce |
Poster only, no video |
| No autoplay sound | muted required |
| Do not block H1 reading | Gradient overlay, WCAG AA text contrast |
aria-hidden on decorative video |
Screen reader ignores background |
Decorative video does not need captions — if it carries substantive content, it should not be background; move to section with controls and captions.
FAQ
Is YouTube/Vimeo embed in hero better?
Not for LCP — iframe loads the full player SDK. Embed makes sense below the fold or in case study sections, not as first viewport.
WebM instead of MP4?
WebM is smaller, but Safari needs MP4 fallback. <source type="video/webm"> + MP4 backup — two cached files, tradeoff OK with CDN.
Will fetchpriority="high" on video help?
Do not use on background video — it raises priority against poster and text. priority only on poster Image.
Hero video and SEO — ranking impact?
The algorithm does not penalize video directly — indirectly via CWV and bounce rate. Slow LCP = worse CrUX = SERP and Ads risk.
Want video hero without LCP penalty?
- Contact us — we design poster-first hero and enforce CI thresholds
- Performance budget — LCP enforcement for teams
- Image optimization — AVIF/WebP hero poster
About the author
We build fast websites, web/mobile apps, AI chatbots and hosting setups — with a focus on SEO and conversion.
Recommended links
From theory to production — Branchly, our hosting stack and shipped work.
