Core Web Vitals w 2025: praktyczny przewodnik po INP, LCP i CLS dla stron, które naprawdę ładują się szybciej

Antoni Kwapisz
02.10.2025

W 2025 roku optymalizacja wydajności przestała być „miłym dodatkiem”, a stała się warunkiem konwersji, widoczności i utrzymania kosztów pozyskania ruchu na rozsądnym poziomie. Po włączeniu Interaction to Next Paint (INP) do zestawu Core Web Vitals i zastąpieniu nim FID, zespół webowy musi patrzeć na wydajność szerzej: nie tylko „jak szybko zaczynamy ładować”, ale „jak szybko strona reaguje na działania użytkownika”. Ten tekst to praktyczny plan: jak zrozumieć progi INP, LCP i CLS, jak je mierzyć w danych terenowych (RUM), a potem – jakimi konkretnymi zabiegami front- i back-endowymi obniżyć czasy i drgania layoutu bez przepisywania całej aplikacji.

Co dokładnie mierzą Web Vitals – i jakie są progi „dobrze”

INP (Interaction to Next Paint) ocenia ogólną responsywność: mierzy opóźnienie od interakcji (klik/tap/klawiatura) do następnego odmalowania UI. „Dobrze” to ≤ 200 ms, „do poprawy” 200–500 ms, „słabo” > 500 ms. Mierz na 75. percentylu wizyt – osobno mobile i desktop – bo to odzwierciedla doświadczenie realnych użytkowników, a nie laboratoryjny ideał.

LCP (Largest Contentful Paint) opisuje, kiedy największy element treści (np. hero-obraz, blok tekstu) staje się widoczny. Cel: ≤ 2,5 s (75. percentyl). Powyżej 4,0 s jest „słabo”.

CLS (Cumulative Layout Shift) to stabilność wizualna – suma niespodziewanych przesunięć elementów podczas ładowania. Cel: < 0,1. Drgający layout rujnuje UX nawet wtedy, gdy nominalnie „ładujemy się szybko”.

Dlaczego „lab” to za mało: RUM, 75. percentyl i segmentacja

Narzędzia laboratoryjne (np. testy w kontrolowanych warunkach) są świetne do reprodukcji błędów, ale o pozycjonowaniu i odczuciu decydują dane terenowe (RUM – Real User Monitoring). Ustal jeden, prosty rytuał: mierzymy INP, LCP, CLS na 75. percentylu, segmentujemy na mobile/desktop, kraj/region i kluczowe szablony (np. strona główna, listing, karta produktu, koszyk). Dopiero w tym przekroju widać, co realnie hamuje sprzedaż.

Największe dźwignie LCP: obraz bohatera, serwer i priorytety ładowania

1) Najcięższa rzecz pierwsza. Zidentyfikuj element, który jest LCP na krytycznych szablonach. W 80% przypadków to hero image albo duży nagłówek/tekst. Jeśli to obraz: serwuj AVIF (fallback WebP/JPEG), ustaw w HTML rozmiar, atrybuty width/height i kompresję adekwatną do rozdzielczości urządzenia (responsywne srcset + sizes).

2) Priorytet pobierania. Dodaj fetchpriority="high" dla obrazu LCP, by dać przeglądarce jednoznaczny sygnał, że to jest zasób numer jeden. W wielu projektach samo to obniża LCP o setki milisekund.

3) Ruch sieciowy z wyprzedzeniem. Jeżeli LCP pochodzi z CDN z innej domeny, użyj preconnect do najważniejszego pochodzenia i dns-prefetch jako tańszego fallbacku dla mniej krytycznych domen. Oszczędzasz RTT na DNS/TCP/TLS i zyskujesz szybsze pierwsze bajty.

4) Serwer i TTFB. LCP jest wrażliwy na wolny Time to First Byte. Cache’uj HTML (Edge/CDN), generuj krytyczne strony statycznie (SSG/ISR), przesuń logikę, która nie jest krytyczna, poza ścieżkę renderowania. W SSR dbaj o strumieniowanie i wczesny flush head-a.

Największe dźwignie INP: „sprzątaj” main-thread i skracaj przerwy między interakcją a odmalowaniem

1) Rozbij ciężkie JavaScript. Zamiast jednego pakietu „na wszystko”, ładuj kod per-widok i per-interakcja (kod split + lazy import). Każdy KB mniej JS to szybsze odpowiedzi UI. Zmierz, które event-handlery trwają najdłużej i zrefaktoruj je do pracy asynchronicznej lub w Web Workerze.

2) Hydration „wyspowa”. W aplikacjach SPA/SSR zastosuj podejście wyspowe: hydratuj tylko interaktywne komponenty (filtry, koszyk), a resztę zostaw statyczną. Zyskujesz natychmiastową możliwość interakcji.

3) Blokujące style i czcionki. Krytyczne CSS inline (kilka KB), reszta media="print" + JS-switch lub rel="preload" z odpowiednim „promowaniem” do stylesheet. Czcionki z font-display: swap i preconnect do dostawcy fontów. Duże, wielowagowe rodziny ogranicz do realnie używanych.

4) Reakcje bez „mikro-lagów”. Przy klikach i zmianach pól formularzy odmaluj drobny feedback (np. pressed state, skeleton) jak najszybciej, a dopiero potem wykonuj droższe operacje (walidacje, fetch). INP mierzy czas do odmalowania – pokaż użytkownikowi, że aplikacja „żyje”.

Stabilność layoutu (CLS): puste miejsce to lepsze miejsce niż skaczące kafelki

1) Zawsze rezerwuj miejsce pod media. Ustal width/height lub współczynnik proporcji (aspect-ratio) dla obrazów, ramek i komponentów osadzanych. W karuzelach i siatkach używaj stałych ramek, nawet jeśli obraz dotrze chwilę później.

2) Reklamy i dynamiczne boxy. Sloty reklamowe i elementy promocyjne muszą mieć z góry zarezerwowaną wysokość. Dla sticky-banerów stosuj bezpieczne „przeskoki” (np. overlay z animacją), a nie wpychanie całej treści w dół.

3) Czcionki i FOIT/FOUT. Preferuj swap albo optional, ogranicz liczbę rodzin i wag. Podmieniaj krój bez zmiany metryk lub zastosuj font metric override, by uniknąć przesunięć po załadowaniu fontu.

Resource Hints i priorytety: kiedy preload, kiedy preconnect, a kiedy fetchpriority

Preload wymusza pobranie konkretnego zasobu, gdy wiesz na pewno, że będzie potrzebny (np. CSS, font, hero-obraz). Preconnect otwiera wcześniej połączenie do innego pochodzenia (DNS+TCP+TLS) – używaj oszczędnie, tylko dla kilku najważniejszych źródeł. dns-prefetch to „tańsza” podpowiedź – tylko DNS – dobra dla mniej krytycznych domen trzecich.

fetchpriority (Priority Hints) nie wymusza pobrania, ale sugeruje przeglądarce, co ma otrzymać wysoki lub niski priorytet. Najlepsze zastosowania: LCP-image (high), obrazki poniżej załamania (low), skrypty niekrytyczne (low). Zawsze testuj w RUM – to wskazówki, a nie twarde rozkazy.

Front-endowa „lista kontrolna” na 2 tygodnie

– Zidentyfikuj LCP na 3 kluczowych szablonach (home/listing/karta) i podnieś jego priorytet ładowania: fetchpriority, wpięcie w HTML, konwersja do AVIF, preconnect do CDN.
– Wprowadź critical CSS (kilka KB) i ogranicz liczbę blokujących plików CSS/JS (maks. 1–2 krytyczne zasoby na head).
– Usuń lub przenieś najcięższe biblioteki (moment, lodash całościowy, gigantyczne UI-kity). Zastąp je tree-shakingiem albo mniejszymi alternatywami.
– Lazy-loaduj obrazki i komponenty poniżej załamania. Upewnij się, że skrótowe miniatury mają zarezerwowane miejsce, by nie powodować CLS.
– Wydziel „wyspy” interaktywne (filtry, koszyk, wyszukiwarka) i opóźnij hydrację reszty. Rozbij event-handlery, które trwają setki milisekund, na kroki asynchroniczne.
– Uporządkuj czcionki: tylko używane wagi, lokalny hosting, preconnect do dostawcy jeśli zewnętrzne, font-display: swap.

Back-end i sieć: TTFB, cache i edge

1) CDN i edge-cache HTML. Nawet dynamiczne strony często mają elementy, które da się keszować z krótkim TTL lub w wariantach per język/kraj. Wyodrębnij „twardo dynamiczne” fragmenty (np. stan koszyka) i resztę serwuj szybko z brzegu.

2) Minimalny HTML na start. Pierwsza odpowiedź powinna zawierać krytyczny content (hero, nagłówek, nadfold). Dalsze moduły doładowuj po odmalowaniu. Strumieniuj SSR, aby UI zaczynał pojawiać się zanim API zwróci pełen zestaw danych.

3) Obrazy i wideo na CDN z transformacją. On-the-fly zmiana rozmiaru i formatu (AVIF/WebP) oraz automatyczny client hints (Width, DPR) to proste, a skuteczne narzędzia do obniżania LCP.

Pomiar i obserwowalność: bez monitoringu optymalizacja to loteria

1) RUM z podziałem na szablony. Mierz INP, LCP, CLS na produkcji, zapisuj do hurtowni (np. BigQuery), raportuj tygodniowo 75. percentyl. Oddzielaj mobile/desktop i kraje. Alarmuj, gdy wskaźniki wyjdą poza progi.

2) Narzędzia lab: Lighthouse/WebPageTest. Wykorzystuj do replikacji i szybkich porównań wariantów. Patrz na waterfall, priorytety zasobów, blokady main-thread i wielkość JS/CSS.

3) A/B w wydajności. Dla zmian krytycznych (np. nowy system obrazów, fontów) odpal test ruchu 50/50 i porównaj wpływ na INP/LCP/CLS oraz konwersję. Wydajność ma wartość biznesową – mierz ją jak każdą inną hipotezę.

„Szybkie zwycięstwa” kontra refaktor: jak planować prace

Najpierw tanie dźwignie (priorytety zasobów, obrazy, fonty, krytyczne CSS, preconnect do CDN), potem większe inwestycje (hydratacja wyspowa, przebudowa routingu, worker-y). Każdą zmianę zamykaj metryką: ilu użytkowników „weszło w zielone” progi na 75. percentylu i jaki to miało wpływ na kluczowe KPI (np. CR, przychód/1000 odsłon).

Antywzorce, które regularnie psują wyniki

– „Uniwersalny” bundel JS ładowany wszędzie, nawet tam, gdzie niepotrzebny.
– Brak rozmiarów dla obrazów i komponentów osadzanych → wysoki CLS.
– Zbyt wiele preconnect do dziesiątek domen (kosztowne; używaj selektywnie).
– Fonty z 6–8 wagami i brak font-display → opóźnienia i przesunięcia.
– Lazy-loading hero-obrazu (LCP) – bohater musi przyjść jako pierwszy, nie „na leniu”.
– „Przecież w Lighthouse mam 95/100” – ale w RUM na 3G w Azji południowej LCP wynosi 4,5 s.

Plan naprawczy na 30 dni

Tydzień 1: audyt RUM (75. percentyl, mobile/desktop, szablony), identyfikacja LCP/INP/CLS per szablon, lista 10 największych zasobów i 10 najdłuższych zadań JS.
Tydzień 2: obrazy: AVIF/WebP, rozmiary, srcset/sizes, fetchpriority="high" dla LCP; fonty: 2–3 wagi, swap, lokalny hosting; CSS: critical inline + redukcja.
Tydzień 3: priorytety i hinty: preconnect (1–2 kluczowe domeny), dns-prefetch dla pozostałych, porządkowanie preload; refaktor najdłuższych event-handlerów pod INP, drobny feedback UI.
Tydzień 4: edge-cache HTML, strumieniowanie SSR lub częściowa statyka, A/B test wydajności, raport wpływu na CR i udział „zielonych” wizyt.

Podsumowanie

Core Web Vitals w 2025 to nie tylko „zaliczyć test”. To zbiór praktyk, które przekładają się na prawdziwe doświadczenie użytkownika: szybkie pierwsze wrażenie (LCP), brak nerwowego „tańca” elementów (CLS) i natychmiastową reakcję na działania (INP). Zaczynaj od danych terenowych i prostych dźwigni (obraz LCP, priorytety, fonty), a dopiero potem sięgaj po większe refaktory. Dzięki temu nie tylko wejdziesz w zielone progi, ale też zobaczysz w analityce to, co liczy się najbardziej: wzrost konwersji i niższy koszt pozyskania.

Źródła

1) https://web.dev/articles/inp — definicja INP i jego rola w responsywności, przykłady i wskazówki optymalizacji.
2) https://web.dev/articles/optimize-inp — praktyczne sposoby poprawy INP i progi: dobre ≤ 200 ms, słabe > 500 ms (75. percentyl).
3) https://web.dev/articles/lcp — definicja i progi LCP (dobre ≤ 2,5 s), zalecenia dot. obrazów i renderowania nadfoldu.
4) https://developers.google.com/search/docs/appearance/core-web-vitals — przegląd Core Web Vitals (w tym CLS < 0,1) i ich znaczenie dla doświadczenia.
5) https://web.dev/articles/vitals-measurement-getting-started — jak mierzyć Web Vitals i dlaczego liczy się 75. percentyl danych terenowych.
6) https://web.dev/blog/inp-cwv-march-12 — ogłoszenie włączenia INP do Core Web Vitals (marzec 2024) i kontekst tej zmiany.
7) https://web.dev/learn/performance/resource-hints — przewodnik po Resource Hints, w tym fetchpriority i kiedy stosować różne wskazówki.
8) https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect — dokumentacja Lighthouse nt. preconnect i kiedy go używać.
9) https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/fetchPriority — MDN: API/praktyka fetchpriority dla obrazów (Priority Hints).
10) https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/dns-prefetch — MDN: różnice i dobre praktyki dns-prefetch vs preconnect (używaj selektywnie).

Zgłoś swój pomysł na artykuł

Więcej w tym dziale Zobacz wszystkie