Przez lata układaliśmy strony na tabelach, float i hackach z position. Dziś mamy CSS Grid, czyli natywny system siatki, który robi to samo w kilku linijkach kodu. Ten artykuł pokazuje, jak działa CSS Grid Layout, jak budować grid template i kiedy wybrać Grid zamiast Flexboksa. Na końcu znajdziesz gotowe przykłady CSS Grid, które wykorzystasz w realnych projektach.
Czym jest CSS Grid Layout?
CSS Grid Layout to dwuwymiarowy system układu strony. Panuje jednocześnie nad kolumnami i wierszami. Flexbox radzi sobie tylko z jedną osią naraz.
Specyfikacja CSS Grid Layout Module Level 1 trafiła do przeglądarek w marcu 2017 roku. Chrome 57, Firefox 52 i Safari 10.1 wprowadziły ją niemal równocześnie. To rzadki przypadek, gdy nowa funkcja CSS od razu działa wszędzie. Według Can I use wsparcie dla Grid przekracza dziś 97% użytkowników na świecie.
Dlaczego to ważne dla Ciebie jako programisty? Bo layout stał się umiejętnością bazową. Rekruterzy oczekują, iż bez problemu zbudujesz responsywną stronę bez frameworka CSS. Grid pozwala to zrobić szybciej i czytelniej niż Bootstrap z jego dwunastoma kolumnami.
W CSS Grid używasz kilku podstawowych pojęć:
- Grid container – element z display: grid.
- Grid items – bezpośrednie dzieci kontenera.
- Grid lines – linie dzielące siatkę, numerowane od 1.
- Grid track – pojedyncza kolumna lub wiersz.
- Grid cell – pojedyncza komórka na przecięciu wiersza i kolumny.
- Grid area – prostokątny obszar złożony z jednej lub kilku komórek.
CSS Grid – tutorial: pierwszy układ krok po kroku
Zacznijmy od najprostszego przykładu. Potrzebujesz kontenera i kilku elementów w środku.
<div> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> </div> .siatka { display: grid; grid-template-columns: 200px 200px 200px; gap: 16px; }To wszystko. Przeglądarka rozkłada sześć elementów w trzech kolumnach i dwóch wierszach. Wiersze tworzą się automatycznie, bo nie zdefiniowałeś/-aś ich jawnie.
Właściwość display: grid
Właściwość display: grid zamienia element w kontener siatki. Istnieje też display: inline-grid, który zachowuje się jak element liniowy na zewnątrz, ale wewnątrz przez cały czas działa jak Grid. W praktyce używasz niemal zawsze wersji blokowej.
Właściwość gap
Właściwość gap ustawia odstępy między komórkami. To skrót dla row-gap i column-gap. Dzięki niej nie potrzebujesz już marginesów i hacków typu :last-child { margin: 0 }.
.siatka { gap: 24px 16px; /* wiersze | kolumny */ }Jednostka fr
Jednostka fr (fraction) to największa nowość Grida. Oznacza ułamek wolnej przestrzeni w kontenerze. Przeglądarka najpierw odlicza sztywne rozmiary i odstępy. Resztę dzieli proporcjonalnie.
.siatka { grid-template-columns: 1fr 2fr 1fr; }Środkowa kolumna jest dwa razy szersza niż boczne. Możesz też mieszkać jednostki: 250px 1fr tworzy stały panel boczny i elastyczną treść.
Grid template: kolumny, wiersze i obszary
Serce CSS Grid to adekwatności z rodziny grid-template-*. To one definiują strukturę siatki. Dobry Grid template czyta się jak plan strony.
grid-template-columns i grid-template-rows
Obie adekwatności przyjmują listę rozmiarów torów. Możesz użyć pikseli, procentów, fr, auto oraz funkcji minmax(), min(), max() i clamp().
.layout { display: grid; grid-template-columns: 240px 1fr; grid-template-rows: auto 1fr auto; min-height: 100vh; }Wartość auto w wierszu oznacza, iż tor dopasuje się do zawartości. Wartość 1fr zajmie całą pozostałą wysokość. Tak działa klasyczny układ z nagłówkiem, treścią i stopką przyklejoną do dołu.
Funkcje repeat() i minmax()
Powtarzanie rozmiarów upraszcza repeat(). Zamiast pisać 1fr 1fr 1fr 1fr, piszesz:
grid-template-columns: repeat(4, 1fr);Funkcja minmax(min, max) ustala zakres rozmiaru toru. Kolumna może mieć na przykład minimum 200 px, a maksimum równe ułamkowi wolnego miejsca.
Pamiętaj o jednej pułapce. Zapis 1fr oznacza w rzeczywistości minmax(auto, 1fr). Długi nierozdzielny tekst potrafi więc rozepchnąć kolumnę. Zapis minmax(0, 1fr) rozwiązuje ten problem.
grid-template-areas
To najbardziej czytelna część Grida. Nazywasz obszary i rysujesz układ strony w CSS jako tekstową makietę.
.strona { display: grid; grid-template-columns: 220px 1fr; grid-template-rows: auto 1fr auto; grid-template-areas: 'naglowek naglowek' 'menu tresc' 'stopka stopka'; min-height: 100vh; } .naglowek { grid-area: naglowek; } .menu { grid-area: menu; } .tresc { grid-area: tresc; } .stopka { grid-area: stopka; }Każdy wiersz tekstu to wiersz siatki. Każde słowo to komórka. Powtórzona nazwa łączy komórki w jeden obszar. Kropka . oznacza pustą komórkę. Obszary muszą tworzyć prostokąty, więc układ w kształcie litery L jest niedozwolony.
Największa zaleta? Zmiana układu na mobile to wymiana kilku linijek w @media, a nie przepisywanie całego CSS.
@media (max-width: 700px) { .strona { grid-template-columns: 1fr; grid-template-areas: 'naglowek' 'menu' 'tresc' 'stopka'; } }Skrót grid-template i linie nazwane
Właściwość grid-template łączy rows, columns i areas w jednym zapisie. Dla początkujących jest mniej czytelna, więc trzymaj się osobnych adekwatności.
Możesz też nadawać nazwy liniom. Robisz to w nawiasach kwadratowych:
grid-template-columns: [start] 1fr [srodek] 2fr [koniec];Linie nazwane przydają się w dużych systemach layoutu. Autorzy bibliotek często definiują tak kolumnę full-width i content.
Pozycjonowanie elementów: linie, span i grid-area
Elementy domyślnie wypełniają komórki po kolei. Możesz to zmienić adekwatnościami grid-column i grid-row.
.hero { grid-column: 1 / 4; /* od linii 1 do linii 4 */ } .baner { grid-column: 1 / -1; /* przez całą szerokość */ } .duzy { grid-column: span 2; grid-row: span 2; }Ujemne numery liczą od końca jawnej siatki. Dlatego 1 / -1 zawsze rozciąga element na wszystkie kolumny. Słowo span mówi, ile torów zajmuje element, bez wskazywania linii.
Właściwość grid-area ma dwie role. Przyjmuje nazwę obszaru albo skrót czterech linii w kolejności: row-start / column-start / row-end / column-end.
Siatka jawna i niejawna
To temat, który często zaskakuje początkujących. Siatka jawna (explicit grid) to tory zdefiniowane przez grid-template-*. Siatka niejawna (implicit grid) powstaje, gdy elementów jest więcej niż komórek.
Domyślnie nowe wiersze mają wysokość auto. Zmienisz to adekwatnością grid-auto-rows.
.galeria { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 180px; }Istnieje też grid-auto-columns oraz grid-auto-flow. Ta ostatnia kontroluje kierunek wypełniania. Wartość dense pozwala zapełniać luki mniejszymi elementami, które pojawiają się później w kodzie.
Uważaj na dense. Zmienia wizualną kolejność elementów względem DOM, co wpływa na dostępność. Wrócimy do tego niżej.
Responsywność bez media queries: auto-fit i auto-fill
Jeden zapis daje responsywną siatkę kart, która sama dobiera liczbę kolumn:
.karty { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px; }Przeglądarka sprawdza, ile kolumn po 250 px zmieści się w kontenerze. Następnie rozciąga je równomiernie. Na telefonie dostaniesz jedną kolumnę, na tablecie dwie, a na monitorze cztery lub pięć. Nie napisałeś/-aś ani jednego @media.
Różnica między auto-fit a auto-fill jest subtelna:
- auto-fill tworzy tyle torów, ile się zmieści, także pustych.
- auto-fit zwija puste tory do zera, więc istniejące elementy się rozciągają.
Przy małej liczbie elementów zobaczysz różnicę od razu. auto-fit wypełni cały rząd. auto-fill zostawi puste miejsce po prawej.
Jest jeszcze jedna pułapka. Przy wąskich ekranach minmax(250px, 1fr) może wywołać poziomy scroll, gdy kontener ma mniej niż 250 px. Bezpieczniejszy zapis używa funkcji min():
grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));Wyrównywanie elementów w CSS Grid
Grid korzysta z tego samego modelu wyrównywania co Flexbox. Wystarczy zapamiętać dwie grupy adekwatności.
Wyrównanie elementów wewnątrz komórek:
- justify-items – oś pozioma (inline).
- align-items – oś pionowa (block).
- place-items – skrót dla obu, na przykład place-items: center.
Wyrównanie całej siatki w kontenerze:
- justify-content – poziomo.
- align-content – pionowo.
- place-content – skrót.
Pojedynczy element nadpiszesz przez justify-self, align-self lub place-self.
Znasz pewnie wieczny problem centrowania elementu na stronie? W Gridzie to dwie linijki:
.centrum { display: grid; place-items: center; min-height: 100vh; }CSS Grid – przykłady z praktyki
Teoria to jedno, a kod w projekcie to drugie. Oto trzy przykłady CSS Grid, które spotkasz w niemal każdej aplikacji webowej.
Przykład 1: klasyczny layout strony
To wariant układu znanego jako holy grail. Nagłówek, menu, treść, panel boczny i stopka. Kiedyś wymagał skomplikowanego kodu. Dziś to kilkanaście linijek.
.app { display: grid; grid-template-columns: 200px minmax(0, 1fr) 240px; grid-template-rows: auto 1fr auto; grid-template-areas: 'head head head' 'nav main aside' 'foot foot foot'; min-height: 100dvh; gap: 16px; }Użyliśmy 100dvh zamiast 100vh. Jednostka dynamic viewport height uwzględnia chowający się pasek adresu na telefonach.
Przykład 2: galeria z elementami o różnej wielkości
Galerię w stylu magazynu zbudujesz bez JavaScriptu.
.galeria { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); grid-auto-rows: 160px; grid-auto-flow: dense; gap: 8px; } .galeria .szeroki { grid-column: span 2; } .galeria .wysoki { grid-row: span 2; } .galeria img { width: 100%; height: 100%; object-fit: cover; }Przykład 3: karty ze stałym układem wewnętrznym
Każdy programista zna problem kart o różnej długości opisu. Przycisk „Czytaj więcej” ląduje na różnych wysokościach. Grid w samej karcie rozwiązuje to prosto:
.karta { display: grid; grid-template-rows: auto 1fr auto; gap: 12px; }Środkowy wiersz pochłania wolne miejsce. Przycisk zawsze siedzi na dole karty. Jeszcze lepiej działa to w połączeniu z subgridem, o którym piszemy niżej.
CSS Grid vs Flexbox: kiedy wybrać który?
Pytanie „CSS Grid vs Flexbox” wraca na każdym szkoleniu i w niemal każdej rozmowie rekrutacyjnej na frontend. Najkrótsza odpowiedź brzmi: to nie są konkurenci. Oba systemy się uzupełniają.
| Cecha | CSS Grid | Flexbox |
| Wymiary | Dwa (wiersze i kolumny) | Jeden (oś główna) |
| Podejście | Layout-first: najpierw siatka, potem treść | Content-first: treść steruje rozmiarem |
| Typowe użycie | Układ całej strony, dashboardy, galerie | Paski nawigacji, rzędy przycisków, komponenty |
| Zawijanie | Naturalne dzięki siatce | Przez flex-wrap, bez wyrównania między wierszami |
| Nakładanie elementów | Proste (ta sama komórka) | Wymaga position |
Praktyczna reguła, której używamy na co dzień:
- Wybierz Grid, gdy planujesz strukturę z wierszami i kolumnami jednocześnie.
- Wybierz Flexbox, gdy układasz elementy w jednej linii i chcesz, by zawartość decydowała o rozmiarach.
- Łącz oba. Grid dla szkieletu strony, Flexbox dla komponentów wewnątrz komórek.
Przykład z życia. Pasek nawigacji z logo po lewej i linkami po prawej to klasyczny Flexbox (justify-content: space-between). Karty produktów w sklepie internetowym to Grid. Przycisk w karcie z ikoną obok tekstu to znów Flexbox.
Jedna uwaga. Gdy po kilku elementach w Flexboksie zaczynasz walczyć z flex-basis i flex-wrap, to znak, iż potrzebujesz Grida. Flexbox z zawijaniem nie wyrówna kolumn między rzędami.
Subgrid: zagnieżdżone siatki, które się dogadują
Przez lata największą wadą Grida było to, iż zagnieżdżona siatka nie znała siatki rodzica. Karta z własnym gridem nie mogła wyrównać tytułu i opisu do sąsiednich kart. Rozwiązaniem jest subgrid.
.lista { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; gap: 24px; } .karta { display: grid; grid-row: span 3; grid-template-rows: subgrid; }Każda karta zajmuje trzy wiersze rodzica. Dziedziczy ich wysokości. Dzięki temu tytuły, opisy i przyciski wszystkich kart są idealnie wyrównane, choćby gdy teksty mają różną długość.
Subgrid działa w Firefoksie od wersji 71 (2019) i w Safari od wersji 16 (2022). Chrome i Edge dołączyły we wrześniu 2023 roku w wersji 117. Od tego czasu funkcja jest dostępna we wszystkich głównych przeglądarkach. Aktualny status sprawdzisz na MDN i w Can I use.
Dostępność i najczęstsze błędy
Grid daje ogromną swobodę wizualną. Ta swoboda ma swoją cenę. adekwatności takie jak order, grid-area czy grid-auto-flow: dense zmieniają tylko wygląd. Kolejność w DOM zostaje bez zmian.
Czytniki ekranu i nawigacja klawiaturą korzystają z kolejności DOM. jeżeli przestawisz elementy wizualnie, użytkownik klawiatury będzie skakał po stronie chaotycznie. To łamie kryterium WCAG 2.4.3 (Focus Order). Zasada jest prosta: układ w HTML ma mieć sens bez CSS, a Grid ma go tylko upiększyć.
Najczęstsze błędy, które widzimy w code review:
- Grid na złym elemencie. display: grid działa tylko na bezpośrednich dzieciach. Wnuki nie trafią do siatki.
- Zapomniane minmax(0, 1fr). Długie słowa lub tabele rozpychają kolumny.
- Użycie procentów razem z gap. Trzy kolumny po 33,33% plus odstępy dają przepełnienie. Użyj fr.
- Sztywne wysokości. Ustawianie height na wierszach psuje się przy zwiększeniu czcionki. Lepsze jest auto, min-content lub minmax().
- Zbyt wiele numerów linii. W dużym projekcie grid-template-areas lub linie nazwane są czytelniejsze.
Do debugowania świetnie nadają się DevTools. Zarówno Chrome, jak i Firefox pokazują nakładkę Grid z numerami linii i nazwami obszarów. Firefox ma tu od lat wyjątkowo dopracowany inspektor.
Wsparcie przeglądarek i przyszłość CSS Grid
W 2026 roku nie musisz już pisać fallbacków dla starych przeglądarek, o ile Twój produkt nie obsługuje Internet Explorera 11. IE11 wspierał tylko starą wersję specyfikacji z prefiksem -ms-, a Microsoft zakończył jego wsparcie w czerwcu 2022 roku. jeżeli musisz zadbać o wyjątkowe przypadki, użyj @supports (display: grid).
Co dalej? Grupa robocza CSS pracuje nad układem typu masonry, czyli siatką w stylu Pinteresta, gdzie elementy układają się kolumnami bez luk. Propozycje obejmują rozszerzenie Grida i osobną wartość display. Eksperymentalne implementacje pojawiają się w przeglądarkach, ale składnia wciąż się zmienia. Przed użyciem w produkcji sprawdź aktualny stan na MDN i w Can I use.
Do tego dochodzą container queries, czyli zapytania o rozmiar kontenera zamiast okna przeglądarki. W połączeniu z Gridem pozwalają budować komponenty, które same dopasowują układ. Container queries działają we wszystkich głównych przeglądarkach od 2023 roku.
Grid wspierają też wszystkie popularne narzędzia. Tailwind CSS oferuje klasy grid-cols-* i col-span-*. Frameworki takie jak Bootstrap 5 mają Grid CSS jako opcję. Coraz więcej zespołów w polskich firmach IT rezygnuje jednak z dodatkowych bibliotek siatki. Natywny CSS wystarcza.
Podsumowanie
CSS Grid to dziś standard układu stron. Daje pełną kontrolę nad wierszami i kolumnami, upraszcza responsywność i skraca kod. W tym tutorialu poznałeś/-aś najważniejsze elementy:
- display: grid, gap i jednostkę fr.
- Budowę grid template z repeat(), minmax() i grid-template-areas.
- Pozycjonowanie przez grid-column, grid-row i span.
- Responsywną siatkę z auto-fit bez media queries.
- Różnice w podejściu CSS Grid vs Flexbox i zasadę łączenia obu.
- Subgrid, dostępność i typowe pułapki.
Najlepszy sposób nauki to praktyka. Weź swoją ostatnią stronę zbudowaną na Flexboksie lub Bootstrapie i przepisz jej szkielet na Grid. Zobaczysz, ile kodu możesz wyrzucić.









