
⚡ Krytyczny CSS: co to jest, jak wygenerować i przyspieszyć ładowanie strony
Strona ładuje się 3 sekundy i odwiedzający odchodzi. Otwiera Pan Google PageSpeed Insights, a tam czerwona diagnoza: „Usuń CSS blokujący renderowanie". Brzmi znajomo? Według danych HTTP Archive za 2025 rok, mediana strony pobiera 7 zewnętrznych arkuszy stylów, a średnia waga CSS przekroczyła 120 KB. Każdy plik w <head> to szlaban między użytkownikiem a treścią.
Problemem nie jest „ciężki" CSS. Przeglądarka nie pokaże ani jednego piksela, dopóki nie załaduje i nie przetworzy WSZYSTKICH stylów. Nawet tych, które odpowiadają za stopkę na 4000. pikselu. Rozwiązaniem jest Critical CSS: technika, która wycina z pełnego zestawu stylów tylko to, co jest potrzebne dla widocznego obszaru ekranu, i osadza to bezpośrednio w <head>. Reszta CSS ładuje się asynchronicznie i nikogo nie wstrzymuje.
Wdrożyliśmy critical CSS we wszystkich projektach na techblogu i zebraliśmy działający proces: od ręcznej generacji w 30 sekund do pełnej automatyzacji przez Gulpa i wtyczki WordPress. Poniżej znajduje się przewodnik krok po kroku, bez lania wody.
💡 Szybki przegląd:
- Zrozumieć mechanikę blokowania renderowania i dlaczego przeglądarka czeka na CSS, nawet gdy HTML jest już gotowy
- Wybrać narzędzie do zadania: darmowy generator online w 10 sekund, Penthouse dla projektów npm lub połączenie WP Rocket / Autoptimize dla WordPressa
- Skonfigurować workflow Gulpa do automatycznej regeneracji critical CSS przy każdym wdrożeniu
- Ominąć typowe pułapki: FOUC, treść JS, problemy z media queries
Czym jest krytyczny CSS i dlaczego przeglądarka zwalnia
Przeglądarka buduje dwie struktury: DOM z HTML i CSSOM ze stylów. Dopóki CSSOM nie jest gotowy, renderowanie jest wstrzymane. To właśnie jest blokujący CSS, strona pozostaje pusta, dopóki nie załadują się wszystkie arkusze stylów z <head>.
Google PageSpeed Insights diagnozuje problem wprost:
Pana strona ma 3 blokujące zasoby CSS. Powoduje to opóźnienie w wyświetlaniu. Żaden element z górnej części strony nie może zostać wyrenderowany, dopóki nie załadują się następujące zasoby.
Termin „above the fold" pochodzi z gazet. W sieci jest to widoczny obszar przed przewinięciem: ~600 px na desktopie, ~900 px na laptopie, ~400 px na smartfonie. Większość deweloperów przyjmuje bezpieczne 1300 px szerokości i 900 px wysokości.
Krytyczny CSS to minimalny zestaw stylów do renderowania właśnie tego obszaru. Siatka, nawigacja, czcionki, górny blok. Reszta jest odkładana i ładuje się asynchronicznie: strona pojawia się natychmiast, a doskłada się w miarę doczytywania.
Liczby są odczuwalne. Według danych Google, osadzenie krytycznego CSS skraca First Contentful Paint o 0,5-1,2 sekundy na urządzeniach mobilnych. Dla e-commerce ma to bezpośredni wpływ na konwersję: badanie Portent wykazało, że strona z FCP poniżej 1 sekundy konwertuje 3 razy lepiej niż strona z FCP wynoszącym 3 sekundy.
Narzędzia do generacji: od darmowego online po komercyjne API
Wygenerowanie krytycznego CSS ręcznie jest niemożliwe, potrzebne jest narzędzie, które wyrenderuje stronę w przeglądarce bezgłowej i wyciągnie tylko użyte style. Oto trzy działające opcje.
Narzędzie | Typ | Koszt | Automatyzacja | Dla kogo |
|---|---|---|---|---|
Critical Path CSS Generator | Online | Darmowy | Nie | Pojedyncze strony, start |
Penthouse | pakiet npm | Darmowy | Tak, przez Gulpa/skrypty | Deweloperzy, przetwarzanie wsadowe |
criticalcss.com | SaaS | Od $10/mies. | Tak, API + WordPress | Produkcja, duże witryny |
Critical Path CSS Generator: online, w 10 sekund
Critical Path CSS Generator Jonasa Olssona to darmowe narzędzie, od którego warto zacząć. Interfejs jest elementarny: wkleja Pan URL strony, wkleja Pan PEŁNY CSS (choćby 200 KB zminifikowanego), klika przycisk i otrzymuje zestaw stylów dla above-the-fold.
Zaleta: zerowy próg wejścia. Nie są potrzebne Node.js, npm ani skrypty. Wada: praca wyłącznie ręczna. Każdą stronę przetwarza Pan osobno, a przy zmianie stylów powtarza proces od nowa. Dla witryny z 5 stronami jest to do przyjęcia, dla 50, już nie.
Twórca generatora uruchomił później komercyjny serwis criticalcss.com, ewolucję tego samego pomysłu z autoaktualizacją, walidacją zrzutami ekranu i API do przetwarzania wsadowego.
Penthouse: konsolowy generator pod Gulpa
Penthouse (ponad 2680 gwiazdek na GitHubie), pakiet npm tego samego autora. Pod spodem Puppeteer i headless-Chromium: otwiera stronę, określa used CSS dla zadanego viewportu i odrzuca resztę.
Instalacja:
1 npm install --save-dev penthouse
Minimalne wywołanie ze skryptu Node:
1 const penthouse = require('penthouse'); 2 const fs = require('fs'); 3 4 penthouse({ 5 url: 'https://example.com', 6 cssString: fs.readFileSync('./style.css', 'utf8'), 7 width: 1300, 8 height: 900 9 }).then(criticalCss => { 10 fs.writeFileSync('./critical.css', criticalCss); 11 });
Szerokość 1300 i wysokość 900, wartości bezpieczne empirycznie. Zapytania mediów szersze niż krytyczny viewport są domyślnie wycinane. Jeśli trzeba je zachować, flaga keepLargerMediaQueries: true.
Ważny niuans: Penthouse uruchamia się z wyłączonym JavaScriptem. Jeśli treść above-the-fold jest generowana przez framework JS, HTML przed hydratacją jest pusty i Penthouse nie znajdzie stylów. Rozwiązanie: renderowanie po stronie serwera (SSR) lub parametr forceInclude z selektorami do wymuszonego zachowania.
WP Rocket i Autoptimize: dwie wtyczki do WordPressa
Jeśli strona działa na WordPressie, ręczne generowanie critical CSS to zbędny ból głowy. Stron jest dużo, szablony się mnożą, style się zmieniają. Dwie wtyczki zamykają zadanie w całości.
WP Rocket, wtyczka premium (59 €/rok za 1 stronę, 119 € za 3, 299 € za 50). Wbudowana opcja „Remove Unused CSS" sama generuje krytyczny CSS dla każdej strony, osadza go w <head>, a resztę CSS ładuje asynchronicznie. Dwa kliknięcia i rekomendacja „Eliminate render-blocking resources" jest spełniona. Bonus: wbudowany hub Rocket Insights oparty na GTmetrix pokazuje metryki wprost z panelu administracyjnego WordPressa.
Autoptimize, bezpłatna wtyczka z opcją „Inline and Defer CSS". Wersja podstawowa generuje JEDEN plik krytycznego CSS dla całej witryny, co w praktyce nie działa (różne strony, różny above-the-fold). Rozwiązanie: integracja z serwisem criticalcss.com (plan WordPress, od 10 $/mies.). Wtyczka automatycznie pobiera krytyczny CSS przez API, osadza go i aktualizuje przy zmianach.
Dla większości użytkowników WordPressa zestaw WP Rocket lub Autoptimize + criticalcss.com zamyka temat całkowicie. Dalej materiał dla tych, którzy piszą strony niestandardowe.

Ręczny workflow: generowanie, wstawianie, weryfikacja
Jeśli koduje Pan stronę bez CMS-a, proces zamyka się w czterech krokach.
Krok 1. Proszę skopiować CAŁY CSS. Proszę zebrać wszystkie style witryny w JEDEN plik. Jeśli pisze Pan w Sassie, proszę skompilować. Jeśli framework typu Bootstrap lub Tailwind, proszę włączyć jego CSS w całości. Proszę nie zgadywać, że „pewnie niepotrzebne", generator sam to rozstrzygnie.
Krok 2. Proszę wygenerować krytyczny CSS przez generator online lub Penthouse. Na wyjściu zminifikowany blok stylów odpowiadający wyłącznie za above-the-fold.
Krok 3. Proszę wstawić krytyczny CSS w <style> wewnątrz <head>. To kluczowe: style inline nie generują dodatkowych żądań HTTP i są przetwarzane przez przeglądarkę natychmiast. Rezultat wygląda mniej więcej tak:
1 <!DOCTYPE html> 2 <html lang="ru"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <style>@charset "UTF-8";*,*::before,*::after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15}body{margin:0;font-family:'Inter',Helvetica,Arial,sans-serif;font-size:1rem;line-height:1.5;color:#222;background:#fff}nav{display:block}.container{max-width:1200px;margin:0 auto;padding:0 20px}</style> 7 <title>Заголовок страницы</title> 8 </head>
Krok 4. Proszę przenieść zewnętrzne CSS i JS z <head> na dół strony, przed zamykającym </body>. Tak, <link rel="stylesheet"> w stopce jest technicznie niepoprawny według specyfikacji, ale w praktyce działa we wszystkich przeglądarkach i rozwiązuje problem blokowania. Alternatywą jest loadCSS od Filament Group do asynchronicznego ładowania stylów bez przenoszenia do stopki.
Finał, weryfikacja przez Google PageSpeed Insights. Rekomendacja „Eliminate render-blocking resources" zniknęła? Wszystko zrobili Państwo prawidłowo.
Gulp + Penthouse: automatyzacja dla projektu bez WordPressa
Każda zmiana stylu wymaga ponownej generacji krytycznego CSS. Robienie tego ręcznie jest zabójczo nudne. Gulp automatyzuje ten proces.
Nasz produkcyjny workflow:
1 // gulpfile.js 2 const gulp = require('gulp'); 3 const penthouse = require('penthouse'); 4 const fs = require('fs'); 5 const urlList = require('./criticalcss-pagelist.json'); 6 7 gulp.task('criticalcss', function () { 8 urlList.urls.forEach(function (item) { 9 penthouse({ 10 url: item.link, 11 css: './css/style.min.css', 12 width: 1300, 13 height: 900, 14 keepLargerMediaQueries: false, 15 renderWaitTime: 100, 16 timeout: 30000 17 }).then(function (criticalCss) { 18 fs.writeFileSync(item.output, criticalCss); 19 console.log('✓ Critical CSS сгенерирован: ' + item.link); 20 }).catch(function (err) { 21 console.error('✗ Ошибка для ' + item.link + ': ' + err.message); 22 }); 23 }); 24 });
Plik criticalcss-pagelist.json z listą URL-i i plików wyjściowych:
1 { 2 "urls": [ 3 { "link": "https://example.com", "output": "./critical/home.php" }, 4 { "link": "https://example.com/about", "output": "./critical/about.php" }, 5 { "link": "https://example.com/contact", "output": "./critical/contact.php" } 6 ] 7 }
Wynik zapisujemy do plików PHP, które opakowują CSS i są wstawiane przez include w <head> odpowiedniego szablonu. Proszę dostosować do swojego stacku: zapisywać do .css, wstawiać przez serwerowy include, jakkolwiek Państwo chcą.
Uruchomienie: gulp criticalcss i wszystkie strony są przetworzone za jednym razem. Proszę podpiąć zadanie w CI/CD podczas wdrożenia, a krytyczny CSS będzie zawsze aktualny.
Z jakimi problemami się Pan/Pani zetknie
Critical CSS to technika, która ma swoje ostre kąty. Oto, co wyłapaliśmy w praktyce.
Flash of unstyled content (FOUC). Krytyczny CSS nie pokrył jakiegoś elementu, użytkownik widzi szarpanie stylów przy pełnym załadowaniu. Przyczyna: treść została wysunięta poza viewport przez absolute lub transform i generator jej nie uwzględnił. Rozwiązanie: flaga forceInclude z selektorem problematycznego elementu.
Treść generowana przez JS. Prawie wszystkie generatory (Penthouse, narzędzie online) uruchamiają się z wyłączonym JavaScriptem. Jeśli landing zbudowano na React, Vue lub Angular, a renderowania po stronie serwera nie ma, HTML jest pusty i generator nie ma czego analizować. Jedyne niezawodne rozwiązanie: włączyć SSR na poziomie frameworka. Alternatywa, ręczne opisanie selektorów przez forceInclude, ale to jest kruche.
Zapytania medialne. Domyślnie Penthouse wycina reguły, których min-width są szersze niż zadany viewport. Jeśli nie poda Pan/Pani keepLargerMediaQueries: true, style desktopowe przepadną, na szerokim ekranie strona „rozjedzie się". Zawsze proszę sprawdzać wynik na rzeczywistych rozdzielczościach.
Cache'owanie. Wygenerował Pan/Pani krytyczny CSS, wdrożył, po tygodniu zmienił styl nagłówka, a w <head> leży stara wersja. Bez automatyzacji w CI/CD będzie Pan/Pani zapominać o ponownym generowaniu. Zadanie w Gulp podczas wdrożenia rozwiązuje problem całkowicie.
⁉️🤔 Często zadawane pytania
Czy trzeba koniecznie stosować Critical CSS na każdej stronie?
Nie, nie na każdej. Jeśli strona ma jeden plik CSS o rozmiarze 20 KB, a FCP jest już poniżej sekundy, korzyść będzie niezauważalna. Ale jeśli w
<head>wiszą 3-4 arkusze stylów o łącznej wadze blisko 100 KB, critical CSS da mierzalny wzrost. Dla landingu z kilku stron wystarczy generator online na 10 minut. Dla sklepu na WordPressie, WP Rocket z kilkoma zaznaczeniami. Proszę kierować się PageSpeed Insights: jeśli rekomendacja „Eliminate render-blocking resources" jest na górze, proszę to robić.
Czy można po prostu przenieść wszystkie <link> do stopki i nie zawracać sobie głowy?
Formalnie nie, specyfikacja HTML wymaga
<link rel="stylesheet">tylko w<head>. W praktyce przeglądarki renderują stronę również z<link>w stopce, ale otrzymuje Pan/Pani błysk nieostylowanej treści (FOUC) przed załadowaniem stylów. Dla wizytówki jest to dopuszczalne, dla projektu komercyjnego, nie. Właściwa ścieżka: krytyczny CSS w<head>inline, asynchroniczne ładowanie reszty przezloadCSSlubmedia="print"zonload="this.media='all'". Przeniesienie do stopki to proteza, która działa kosztem wizualnego szarpania.
Co się zmieniło wraz z pojawieniem się HTTP/3 i Early Hints?
HTTP/3 i 103 Early Hints pozwalają przeglądarce rozpocząć ładowanie krytycznych zasobów przed otrzymaniem pełnej odpowiedzi serwera. Skraca to opóźnienie, ale nie znosi blokowania renderowania: style i tak muszą się załadować i zostać sparsowane. Early Hints i critical CSS działają w parze, a nie zamiast siebie: Early Hints przyspiesza dostarczanie, critical CSS, moment pierwszego renderowania. Dwie techniki wzmacniają się nawzajem.
Dlaczego Penthouse nie był aktualizowany od 4 lat, czy jest jeszcze aktualny?
Ostatnie wydanie Penthouse (v2.3.3) ukazało się w 2022 roku, ale pakiet pozostaje sprawny: pod maską Puppeteer i Chromium, które są stabilne. Krytyczna funkcjonalność, generowanie used CSS dla zadanego viewportu, nie wymaga częstych aktualizacji. Alternatywa, Critical od Addy'ego Osmaniego (12 000+ gwiazdek), który jest aktualizowany aktywniej i również integruje się z Gulp/Grunt.
Jak postępować ze stronami dynamicznymi, gdzie treść zależy od użytkownika?
Dla stron z personalizacją (konto osobiste, koszyk, dashboard) krytyczny CSS generuje się nie dla konkretnego użytkownika, a dla ogólnej struktury: nagłówek, sidebar, siatka. Treść dynamiczna trafia do części asynchronicznej. Jeśli bez stylów dla bloku użytkownika above-the-fold układ się łamie, proszę dodać odpowiednie selektory przez
forceInclude. Proszę generować krytyczny CSS na podstawie ogólnej struktury strony, a spersonalizowane bloki pozostawiać w ładowaniu asynchronicznym zforceIncludedla krytycznie ważnych.
Czy warto wdrożyć Critical CSS w Pana/Pani projekcie
Jeśli strona ładuje więcej niż jeden plik CSS w <head>, critical CSS da mierzalny wzrost szybkości. Dla landingu z trzech stron wystarczy generator online na 10 minut. Dla bloga lub sklepu na WordPressie, dwa zaznaczenia w WP Rocket. Dla projektu niestandardowego, godzina na konfigurację Gulpa i Penthouse zwraca się przy pierwszym wdrożeniu.
Próg wejścia jest niższy, niż się wydaje. Proszę wziąć darmowy generator online, skopiować CSS swojej strony, wkleić i po 30 sekundach zobaczy Pan/Pani wynik. A kiedy zechce Pan/Pani automatyzacji, proszę wrócić do sekcji z workflow Gulpa: ona zamknie temat całkowicie. Przyspieszenie ładowania dwukrotnie w ciągu kilku godzin pracy to transakcja, z której trudno zrezygnować.



