CSS Flexbox – jak ułatwić sobie układanie elementów na stronie

geek.justjoin.it 3 dni temu

Jeszcze kilkanaście lat temu układanie elementów na stronie oznaczało walkę z float, inline-block i hackami z clearfix. Dziś CSS flex załatwia większość takich zadań w kilku linijkach. Flexbox to jedno z podstawowych narzędzi frontendowca i temat, który regularnie wraca na rozmowach rekrutacyjnych na stanowiska juniorskie.

W tym tutorialu przejdziemy przez cały model flexbox layout. Poznasz adekwatności kontenera i elementów, zobaczysz CSS flex – przykłady z prawdziwych interfejsów i dowiesz się, kiedy lepiej sięgnąć po CSS Grid. Na końcu znajdziesz listę błędów, które popełnia większość początkujących.

Czym jest CSS Flexbox?

Flexbox (pełna nazwa: CSS Flexible Box Layout) to moduł CSS do układania elementów w jednym wymiarze: w wierszu albo w kolumnie. Służy do rozmieszczania elementów, wyrównywania ich i rozdzielania wolnego miejsca między nimi.

Specyfikację utrzymuje W3C. Flexbox jest dziś wspierany we wszystkich aktualnych przeglądarkach. Aktualną tabelę kompatybilności sprawdzisz na stronie Can I use. Nie potrzebujesz prefiksów ani polyfilli, o ile nie obsługujesz bardzo starych przeglądarek.

Flexbox rozwiązuje problemy, które wcześniej bolały każdego frontendowca:

  • centrowanie w pionie i w poziomie,
  • równe wysokości kolumn bez sztuczek,
  • rozkładanie elementów z równymi odstępami,
  • zmiana kolejności elementów bez ruszania HTML-a,
  • elastyczne dopasowanie elementów do dostępnego miejsca.

Podstawy: kontener i elementy

Flexbox działa na relacji rodzic–dziecko. Rodzic to flex container, jego bezpośrednie dzieci to flex items. Zagnieżdżone wnuki nie są elementami flex, chyba iż same dostaną display: flex.

html <div> <div>1</div> <div>2</div> <div>3</div> </div> css .container { display: flex; }

Jedna deklaracja zmienia zachowanie całego układu. Elementy, które wcześniej leżały jeden pod drugim jako bloki, ustawiają się teraz w jednym rzędzie. Domyślnie każdy zajmuje tyle miejsca, ile potrzebuje jego zawartość.

Istnieje też display: inline-flex. Kontener zachowuje się wtedy jak element liniowy, więc nie zajmuje całej szerokości rodzica. Używasz go rzadziej, na przykład do przycisków z ikoną i tekstem.

Oś główna i oś poprzeczna

Żeby zrozumieć flexbox, musisz poznać dwie osie:

  • oś główna (main axis) – kierunek, w którym układają się elementy,
  • oś poprzeczna (cross axis) – kierunek prostopadły do osi głównej.

Domyślnie oś główna biegnie poziomo, od lewej do prawej. Oś poprzeczna biegnie pionowo. Gdy zmienisz kierunek na kolumnę, osie zamieniają się miejscami.

To najważniejsza rzecz w całym module. Większość pomyłek wynika z tego, iż ktoś zapomniał, która oś jest którą.

Właściwości kontenera flex

Kontener ma sześć najważniejszych adekwatności. Poznasz je po kolei.

flex-direction – kierunek układania

Ta adekwatność ustawia oś główną.

css .container { display: flex; flex-direction: row; /* domyślnie: w poziomie, od lewej */ /* row-reverse – w poziomie, od prawej */ /* column – w pionie, od góry */ /* column-reverse – w pionie, od dołu */ }

Wartość row to domyślny układ w poziomie. Wartość column przydaje się w formularzach, panelach bocznych i widoku mobilnym. Warianty -reverse odwracają kolejność wizualną, ale nie zmieniają kolejności w DOM. Do tego wrócimy w sekcji o dostępności.

flex-wrap – zawijanie elementów

Domyślnie flexbox próbuje zmieścić wszystko w jednej linii. Elementy się kurczą, a gdy nie mogą, wychodzą poza kontener. adekwatność flex-wrap pozwala je zawijać do kolejnych linii.

css .container { display: flex; flex-wrap: wrap; /* nowe linie, gdy brakuje miejsca */ /* nowrap – domyślnie, jedna linia */ /* wrap-reverse – zawijanie w odwrotnym kierunku */ }

To adekwatność, dzięki której zbudujesz siatkę kart bez media queries.

flex-flow – skrót

flex-flow łączy flex-direction i flex-wrap:

css .container { flex-flow: row wrap; }

justify-content – wyrównanie na osi głównej

Ta adekwatność rozdziela wolne miejsce wzdłuż osi głównej. Używasz jej najczęściej.

css .container { display: flex; justify-content: space-between; }

Dostępne wartości:

  • flex-start – elementy na początku osi (domyślnie),
  • flex-end – elementy na końcu osi,
  • center – elementy na środku,
  • space-between – pierwszy i ostatni przy krawędziach, reszta równo pomiędzy,
  • space-around – równe odstępy wokół każdego elementu, więc na brzegach jest o połowę mniej miejsca,
  • space-evenly – dokładnie równe odstępy wszędzie, także przy krawędziach.

align-items – wyrównanie na osi poprzecznej

align-items decyduje, jak elementy ustawiają się w poprzek osi głównej.

css .container { display: flex; align-items: center; }

Możliwe wartości:

  • stretch – elementy rozciągają się na całą wysokość linii (domyślnie),
  • flex-start – wyrównanie do początku osi poprzecznej,
  • flex-end – wyrównanie do końca,
  • center – wyśrodkowanie,
  • baseline – wyrównanie do linii bazowej tekstu.

To dzięki domyślnemu stretch masz równe wysokości kart w jednym rzędzie. Nie potrzebujesz żadnych hacków.

align-content – wyrównanie wielu linii

align-content działa tylko wtedy, gdy kontener ma więcej niż jedną linię. Czyli gdy ustawiłeś/-aś flex-wrap: wrap i elementy faktycznie się zawinęły. Kontener musi też mieć wolne miejsce w osi poprzecznej, na przykład ustaloną wysokość.

css .container { display: flex; flex-wrap: wrap; height: 400px; align-content: space-between; }

Wartości są podobne jak w justify-content. jeżeli align-content nic nie robi, sprawdź najpierw, czy na pewno masz wiele linii.

gap – odstępy między elementami

gap to jedna z najlepszych rzeczy, jakie dostał flexbox. Zastępuje marginesy doklejane do elementów i problem „ostatniego elementu bez marginesu”.

css .container { display: flex; gap: 16px; /* te same odstępy w obu kierunkach */ /* row-gap: 16px; – odstęp między liniami */ /* column-gap: 24px; – odstęp między elementami w linii */ }

Przez długi czas gap działał tylko w CSS Grid. Dziś obsługują go wszystkie aktualne przeglądarki. jeżeli utrzymujesz starszy projekt, sprawdź w Can I use, czy twoja grupa docelowa nie wymaga wsparcia dla starszych wersji.

Właściwości elementów flex

Teraz zajmiemy się dziećmi kontenera. Tu flexbox pokazuje, dlaczego nazywa się „elastyczny”.

flex-grow, flex-shrink i flex-basis

Te trzy adekwatności decydują o rozmiarze elementu na osi głównej.

  • flex-basis – rozmiar początkowy, zanim flexbox rozdzieli wolne miejsce. Domyślnie auto, czyli rozmiar wynika z width albo z zawartości.
  • flex-grow – jaką część wolnego miejsca element może przejąć. Domyślnie 0, czyli nie rośnie.
  • flex-shrink – jak mocno element może się kurczyć, gdy brakuje miejsca. Domyślnie 1, czyli kurczy się.

Weźmy przykład. Kontener ma 900 px szerokości. Trzy elementy mają po 200 px, razem 600 px. Zostaje 300 px wolnego miejsca.

css .item { flex-basis: 200px; } .item-a { flex-grow: 1; } .item-b { flex-grow: 2; } .item-c { flex-grow: 0; }

Wolne 300 px dzielimy w proporcji 1:2:0. Element A dostaje 100 px, B dostaje 200 px, C nic. Ostatecznie A ma 300 px, B ma 400 px, a C zostaje przy 200 px.

flex – skrót, którego używasz na co dzień

W praktyce rzadko zapisujesz trzy adekwatności osobno. Używasz skrótu flex:

css .item { flex: 1; /* to samo co: flex: 1 1 0% */ }

Najczęstsze wartości:

  • flex: 1 – element rośnie i kurczy się, a bazowy rozmiar to 0. Wolne miejsce dzielą równo wszystkie takie elementy.
  • flex: auto – odpowiednik 1 1 auto. Rozmiar bazowy wynika z zawartości, a wolne miejsce jest dzielone.
  • flex: none – odpowiednik 0 0 auto. Element ma stały rozmiar i nie zmienia go.
  • flex: 0 0 200px – sztywna szerokość 200 px, bez rośnięcia i kurczenia.

Rozróżnienie flex: 1 i flex: auto często zaskakuje. Przy flex: 1 elementy dostają równą szerokość niezależnie od zawartości. Przy flex: auto szerokość zależy od zawartości, a dopiero potem dzielone jest wolne miejsce.

align-self – wyjątek od reguły

align-self pozwala pojedynczemu elementowi ignorować align-items kontenera.

css .container { align-items: flex-start; } .special { align-self: flex-end; }

Przyjmuje te same wartości co align-items, plus auto.

order – zmiana kolejności

Domyślnie każdy element ma order: 0. Elementy z mniejszą wartością pojawiają się wcześniej, z większą później.

css .item-last { order: 1; } .item-first { order: -1; }

Użyj tego rozsądnie. Zmiana kolejności wizualnej nie zmienia kolejności dla czytników ekranu i nawigacji klawiaturą. O tym więcej w sekcji o błędach.

Magia margin: auto

Automatyczne marginesy działają we flexboxie inaczej niż w zwykłym układzie. Pochłaniają całe wolne miejsce w swoim kierunku.

css .navbar { display: flex; } .navbar .login { margin-left: auto; }

Przycisk „Zaloguj” wyląduje na prawej krawędzi, a reszta elementów zostanie po lewej. To jeden z najprostszych sposobów na budowę nawigacji.

CSS flex – przykłady z praktyki

Teoria jest ważna, ale flexboxa uczysz się przez budowanie. Poniżej cztery wzorce, które spotkasz w prawie każdym projekcie.

Przykład 1: idealne centrowanie

Klasyczny problem: wyśrodkuj element w pionie i poziomie.

css .hero { display: flex; justify-content: center; align-items: center; min-height: 100vh; }

Wcześniej wymagało to pozycjonowania absolutnego i transformacji. Teraz to trzy linijki.

Przykład 2: nawigacja

html <nav> <a href="/">Just Geek IT</a> <ul> <li><a href="/blog">Blog</a></li> <li><a href="/zarobki">Zarobki</a></li> <li><a href="/kariera">Kariera</a></li> </ul> <a href="/login">Zaloguj</a> </nav> css .navbar { display: flex; align-items: center; gap: 24px; padding: 0 24px; } .menu { display: flex; gap: 16px; list-style: none; margin: 0; padding: 0; } .login { margin-left: auto; }

Zwróć uwagę na zagnieżdżenie. .navbar jest kontenerem flex dla logo, menu i przycisku. Samo .menu jest osobnym kontenerem flex dla elementów listy.

Przykład 3: responsywna siatka kart

css .cards { display: flex; flex-wrap: wrap; gap: 24px; } .card { flex: 1 1 280px; }

Zapis flex: 1 1 280px czytasz tak: karta ma preferowaną szerokość 280 px, może rosnąć i może się kurczyć. Gdy brakuje miejsca, karty zawijają się do kolejnej linii. Na wąskim ekranie masz jedną kolumnę, na szerokim trzy lub cztery. Bez ani jednego media query.

Jest jedno zastrzeżenie. Ostatnia linia kart rozciągnie się na całą szerokość, jeżeli zostanie w niej mniej elementów niż w pozostałych. jeżeli chcesz równych kolumn we wszystkich liniach, lepszy będzie CSS Grid.

Przykład 4: układ z przyklejoną stopką (sticky footer)

Stopka zawsze na dole okna, choćby gdy treści jest mało.

css body { display: flex; flex-direction: column; min-height: 100vh; margin: 0; } main { flex: 1; }

Element main zajmuje całe wolne miejsce, więc footer ląduje na dole. Ten wzorzec to jeden z najczęstszych przykładów użycia flexbox layout w prawdziwych projektach.

Flexbox czy CSS Grid?

To pytanie pada w każdej dyskusji. Odpowiedź jest prosta: to narzędzia do różnych zadań i świetnie się uzupełniają.

Flexbox jest jednowymiarowy. Układasz elementy w wierszu albo w kolumnie. Rozmiar elementów wynika głównie z ich zawartości.

CSS Grid jest dwuwymiarowy. Definiujesz jednocześnie wiersze i kolumny. Układ wynika z siatki, którą narzucasz z góry.

Praktyczna zasada:

  • Flexbox: komponenty, paski nawigacji, rzędy przycisków, wyrównywanie zawartości kart, formularze.
  • Grid: układ całej strony, galerie, dashboardy, wszystko, co ma równe kolumny i wiersze naraz.

W prawdziwych projektach łączysz oba. Grid ustawia szkielet strony, a flexbox układa zawartość wewnątrz poszczególnych komórek.

Najczęstsze błędy i pułapki flexboxa

Poniższe problemy zgłaszają początkujący w każdym kursie. Znajomość ich oszczędzi ci godzin debugowania.

1. Mylenie osi

Gdy ustawisz flex-direction: column, justify-content działa w pionie, a align-items w poziomie. jeżeli „nic nie działa”, najpierw sprawdź kierunek.

2. justify-content w kolumnie nie robi nic

Kontener w układzie kolumnowym ma domyślnie wysokość wynikającą z zawartości. Nie ma więc wolnego miejsca do rozdzielenia. Ustaw height albo min-height, a adekwatność zadziała.

3. Tekst wylewa się z elementu

To jeden z najbardziej zaskakujących problemów. Elementy flex mają domyślnie min-width: auto. Oznacza to, iż nie zmniejszą się poniżej szerokości swojej zawartości. Długi, niełamliwy ciąg znaków, na przykład adres URL, rozepchnie układ.

css .item { min-width: 0; /* pozwala elementowi się zwęzić */ overflow-wrap: anywhere; }

Ten sam mechanizm dotyczy min-height w kolumnach.

4. Obrazki i elementy rozciągają się nieoczekiwanie

Domyślne align-items: stretch rozciąga elementy do pełnej wysokości linii. jeżeli nie chcesz tego efektu, ustaw align-items: flex-start albo align-self na konkretnym elemencie.

5. Nadużywanie width zamiast flex-basis

W kontenerze flex flex-basis ma pierwszeństwo przed width na osi głównej. Mieszanie obu prowadzi do zagadek. Trzymaj się jednej konwencji i najlepiej używaj skrótu flex.

6. Zmiana kolejności kosztem dostępności

Właściwości order i row-reverse zmieniają tylko wygląd. Użytkownicy czytników ekranu i klawiatury poruszają się w kolejności z DOM. Gdy rozjedzie się z tym, co widać, nawigacja staje się dezorientująca. Specyfikacja WCAG wymaga logicznej kolejności fokusu. Kolejność zmieniaj w HTML-u, a order zostaw na drobne korekty wizualne.

Jak ćwiczyć flexbox?

Przeczytanie tutorialu to początek. Żeby naprawdę opanować flex CSS, zrób kilka rzeczy:

  1. Zbuduj od zera nawigację, hero z centrowaniem i siatkę kart. Nie kopiuj gotowców.
  2. Pobaw się w narzędziach developerskich. Chrome i Firefox mają podgląd flexboxa w DevTools. Zobaczysz osie, odstępy i rozmiary elementów.
  3. Zagraj w gry edukacyjne. Flexbox Froggy i Flexbox Zombies uczą adekwatności przez zabawę.
  4. Czytaj dokumentację. MDN Web Docs ma świetne opisy każdej adekwatności i przykłady na żywo.
  5. Zrób refaktoring. Weź stary projekt oparty na float i przepisz układ na flexbox.

Podsumowanie

Flexbox to fundament nowoczesnego CSS. Pamiętaj o kilku zasadach:

  • Kontener i elementy. display: flex na rodzicu zmienia zachowanie jego bezpośrednich dzieci.
  • Dwie osie. justify-content działa na osi głównej, align-items na poprzecznej.
  • Elastyczność. flex-grow, flex-shrink i flex-basis, najczęściej zapisywane jako flex, decydują o rozmiarach elementów.
  • gap zastępuje marginesy między elementami.
  • Flexbox do komponentów, Grid do układu całej strony.
  • Uważaj na min-width: auto i na dostępność przy zmianie kolejności elementów.
Idź do oryginalnego materiału