TL;DR
Video w sekcji hero wygląda premium w Figma — w Lighthouse mobile LCP często skacze powyżej 4 s, bo <video autoplay> konkuuruje z obrazem poster, fontem i skryptami analityki o pierwsze paint. LCP elementem bywa klatka wideo, poster lub nagłówek obok — musisz to zmierzyć, nie zgadywać. Rozwiązanie produkcyjne: poster WebP/AVIF jako LCP, wideo preload="none" lub ładowane po requestIdleCallback, na mobile statyczny hero zamiast wideo. Hosting na DevStudioIT Cloud z CDN nie naprawi 8 MB pliku MP4 — optymalizacja assetu i warunkowe renderowanie w Next.js tak. Poniżej: decyzja design/dev, kod komponentu i progi kiedy w ogóle używać video hero.
Dla kogo to jest
- Stron firmowych B2B z briefem „chcemy wideo w tle jak Apple"
- Zespołów z LCP > 2,5 s po dodaniu hero video w ostatnim sprincie
- Marketingu mierzącego konwersje z Google Ads — wolny landing = wyższy CPC
- Developerów Next.js szukających kompromisu bez odrzucenia całego pomysłu wideo
- Projektów po redesignie, gdzie CrUX spadł po wymianie statycznego hero na MP4
Fraza (SEO)
video hero lcp, wydajność wideo strona firmowa, poster video nextjs, lazy load hero video, largest contentful paint wideo, autoplay background performance 2026
Dlaczego video hero dominuje nad LCP
LCP mierzy czas do wyrenderowania największego elementu w viewport. Przy pełnoekranowym <video>:
| Element kandydujący na LCP | Typowy czas (mobile 4G) | Problem |
|---|---|---|
| Pierwsza klatka wideo (bez poster) | 3–6 s | Dekoder + download fragmentu MP4 |
Poster <video poster="..."> |
1,5–3 s | OK jeśli poster zoptymalizowany |
| H1 obok wideo | 1,2–2 s | Video nie powinno być LCP |
| Statyczny obraz hero | 0,8–1,8 s | Benchmark dla strony firmowej |
Autoplay w tle wymaga atrybutów muted, playsinline, loop — przeglądarka i tak pobiera początek pliku zanim pierwsza klatka będzie gotowa. Plik 5 MB MP4 to więcej niż cały budżet JS landing page.
Poster first — wzorzec LCP-safe
// 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>
);
}| Decyzja | Wpływ LCP | UX |
|---|---|---|
Image priority na poster |
LCP ≈ poster | Natychmiastowy wizual |
preload="none" na video |
Brak konkuencji o bandwidth | Krótkie opóźnienie startu wideo |
| Video po idle | LCP już zmierzone na poster | Akceptowalne na desktop |
prefers-reduced-motion |
Tylko poster | Dostępność + performance |
Mobile vs desktop — warunkowe hero
Na mobile wyłącz video — oszczędność danych i 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" />;
}Alternatywa: CSS @media (max-width: 768px) ukrywa <video>, ale plik może i tak być w bundlu — server-side branch jest pewniejszy.
| Breakpoint | Rekomendacja |
|---|---|
| < 768 px | Statyczny poster AVIF |
| 768–1024 px | Krótkie wideo ≤ 2 MB, 720p |
| > 1024 px | Loop 1080p ≤ 4 MB po optymalizacji |
Optymalizacja pliku wideo — nie tylko lazy load
| Parametr | Wartość docelowa | Narzędzie |
|---|---|---|
| Długość loop | 5–12 s | Montaż |
| Rozmiar pliku | ≤ 2 MB mobile source, ≤ 4 MB desktop | ffmpeg |
| Kodek | H.264 baseline lub H.265 jeśli fallback | HandBrake, ffmpeg |
| Rozdzielczość | 1280×720 hero wystarczy | Scale w 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 przenosi moov atom na początek — szybsze pierwsze klatki nawet gdy video jest LCP (unikaj tego scenariusza).
Serwuj MP4 z DevStudioIT Cloud CDN z długim Cache-Control — ten sam origin co strona, bez dodatkowego DNS do Vimeo/Youtube (embed iframe to osobny problem third-party).
Alternatywy gdy video hero odpada
| Alternatywa | LCP | Efekt wizualny |
|---|---|---|
| Krótki loop GIF → zamieniony na MP4 | Średni | Lepszy niż GIF 15 MB |
| CSS gradient + subtelna animacja | Niski | Nowoczesny, lekki |
| Sekwencja WebP (sprite) | Niski–średni | „Pseudo-video" 8–12 klatek |
| Statyczny hero + play button → modal | Niski | Wideo na żądanie, nie LCP |
| Rive / Lottie lekka animacja | Średni | Ilustracja zamiast footage |
Brief „musimy mieć wideo" — modal on click spełnia marketing (materiał na stronie) bez kary LCP.
Pomiar — jak potwierdzić, że poster jest LCP
- Lighthouse mobile → sekcja LCP → element selector
- Chrome DevTools → Performance → Largest Contentful Paint marker
web-vitalszreportAllChangesna staging
Jeśli LCP wskazuje <video> — poster nie działa jako pierwszy paint (brak priority na Image lub video bez preload="none" ładuje się wcześniej).
Integracja z performance budget
W Lighthouse CI assert LCP ≤ 2500 ms na /pl z hero. PR dodający <video autoplay> bez poster-first powinien failować. Design review: wideo to osobna kategoria budżetu obok JS i fontów.
Brief dla klienta — jak sprzedać kompromis marketingowi
Marketing często chce „filmik w tle" bo konkurencja ma. Przedstaw liczby, nie techniczny żargon:
| Argument | Dane | Propozycja |
|---|---|---|
| Wolny LCP | +0,5 s ≈ spadek konwersji 7–10% (branżowe benchmarki landing) | Poster + wideo po idle |
| Mobile traffic | 60–70% B2B | Statyczny hero mobile |
| Koszt produkcji | 4K footage ≠ lepszy loop | 720p 8 s wystarczy |
| Brand story | Wideo ważne | Modal z pełnym materiałem 30 s |
Demo side-by-side w Lighthouse: strona z autoplay MP4 vs poster-first — ten sam design, różnica 2 s LCP przekonuje PO szybciej niż slajd o „Core Web Vitals".
Dostępność video hero
| Wymóg | Implementacja |
|---|---|
prefers-reduced-motion: reduce |
Tylko poster, zero video |
| Brak dźwięku autoplay | muted obowiązkowe |
| Nie przeszkadzać w czytaniu H1 | Overlay z gradientem, kontrast tekstu WCAG AA |
aria-hidden na dekoracyjnym video |
Screen reader ignoruje tło |
Video dekoracyjne nie wymaga napisów — jeśli niesie treść merytoryczną, nie powinno być w tle; przenieś do sekcji z kontrolkami i captions.
FAQ
Czy YouTube/Vimeo embed w hero jest lepsze?
Nie dla LCP — iframe ładuje cały player SDK. Embed sensowny poniżej fold lub w sekcji case study, nie jako pierwszy viewport.
WebM zamiast MP4?
WebM mniejszy, ale Safari wymaga MP4 fallback. <source type="video/webm"> + MP4 jako backup — dwa pliki do cache, tradeoff OK przy CDN.
Czy fetchpriority="high" na video pomoże?
Nie używaj na background video — podniesiesz priorytet konkurencji wobec poster i tekstu. priority tylko na poster Image.
Hero video a SEO — wpływ na ranking?
Bezpośrednio algorytm nie karze wideo — pośrednio przez CWV i bounce rate. Wolny LCP = gorsze dane CrUX = ryzyko w SERP i Ads.
Chcesz hero wideo bez kary LCP?
- Skontaktuj się z nami — zaprojektujemy hero poster-first i wdrożymy progi w CI
- Performance budget — egzekwowanie LCP w zespole
- Optymalizacja obrazów — poster hero w AVIF/WebP
O autorze
Budujemy szybkie strony WWW, aplikacje web/mobile, chatboty AI i hosting — z naciskiem na SEO i konwersję.
Przydatne linki
Od teorii do produkcji — Branchly, hosting i realizacje.
