Podstawy flexbox
Szybki kurs Flexbox, czyli poradnik CSS (z przykładem layoutu „mobile first”) dla tych, którzy mają już dość tworzenia layoutów przy użyciu float i margin. Flexbox pozwala na łatwe tworzenie layoutów, ułatwiając dodatkowo zmianę layoutu dla różnych urządzeń przez media queries.
Spis treści
Co to jest ten flex, flexbox?
Flexbox (z ang. Flex Box, czyli Flexible Box) to jedna z wielu metod na tworzenie layoutu – zarówno strony, jak i poszczególnych elementów strony – który będzie elastyczny, tzn. będzie się dostosowywał do wymiarów ekranu. Pozwala w łatwy sposób utworzyć layout strony, oraz zmodyfikować go odpowiednio dla różnych wielkości ekranu. Dla tych którzy nie lubią podejścia mobile first, sprawdzi się równie dobrze w podejściu desktop first.
Dzięki flexbox unikniesz w wielu przypadkach dodatkowych wrapperów (<div class="wrapper">
), aby jakieś elementy ułożyć obok siebie. Nie będą też potrzebne float’y, ujemne marginesy ani kombinowanie z nadawaniem wysokości elementom, aby dwa znajdujące się obok siebie były tak samo wysokie.
Czy flexbox nadaje się do każdego layoutu?
I tak i nie… W zasadzie każdy layout da się zaprojektować z użyciem flexbox, ale w celu uzyskania bardziej zaawansowanych potrzebne będą dodatkowe wrappery. Przy takich być może lepszą opcją będzie layout oparty o CSS grid.
Zaczynamy tworzyć layout przy użyciu flexbox
Powiedzmy, że chcemy stworzyć tradycyjny layout z nagłówkiem, menu, stopką, treścią właściwą i jakimś sidebarem. W dużym skrócie, html zrobimy taki:
<body> <header>Nagłówek</header> <article>Jakaś treść właściwa</article> <aside>Panel boczny</aside> <nav>Nawigacja</nav> <footer>Stopka</footer> </body>
Kolejność nie jest przypadkowa – nawigacja celowo jest nisko, żeby jej zawartość nie była pierwszą treścią na stronie – dzięki temu w wynikach wyszukiwarek nie pojawi się kawałek menu, tylko treść właściwa ze strony. Dla wyższych rozdzielczości ekranu przeniesiemy ją łatwo nad treść właściwą.
Layout na najmniejsze rozdzielczości ekranu, czyli telefony komórkowe
Teraz dodajmy jakieś proste stylowanie + ustawmy odpowiednią kolejność, aby strona jakoś wyglądała – dla telefonów może to być wersja jeden bloczek pod drugim. Zatem nasz CSS będzie wyglądał tak:
body {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0;
padding: 0;
}
body > * {
flex-basis: 100%;
margin: 0;
padding: 1em 2em;
box-sizing: border-box;
}
header {
background: green;
}
nav {
background: yellow;
}
article {
background: cyan;
}
aside {
background: pink;
}
footer {
background: red;
}
Nasz layout powinien wyglądać tak:
Teraz kilka słów wyjaśnienia:
- W tak prostym layoucie wszystkie elementy są na tym samym poziomie drzewa DOM (tu: bezpośrednio w body)
- W elemencie nadrzędnym (tu: body) ustawiamy
display: flex
– to powoduje, że wszystkie elementy występujące bezpośrednio w body będą układane za pomocą flexbox - Ustawienie
flex-direction: row
powoduje, że domyślnie elementy będą się układać obok siebie (od lewej do prawej, chyba że zmienimy to za pomocąflex-direction: row-reverse
) - Parametr
flex-wrap: wrap
pozwala „spadać” elementom poniżej, jeśli nie mieszczą się w jednej linii - Dla wszystkich bezpośrednich dzieci taga body ustawiamy
flex-basis: 100%
(domyślnie nadaj każdemu elementowi 100% szerokości), czyli pomimo ustawienia flex-direction, elementy będą na całą szerokość strony (pamiętajmy, że to jest wersja na urządzenia mobilne, więc mało jest miejsca na szerokości ekranu) - Dodatkowy parametr (nie związany bezpośrednio z flexbox)
box-sizing: border-box
powoduje, że dodanie paddingu nie zwiększy szerokości bloczka – padding będzie liczony „do wewnątrz”.
Zatem mamy prosty layout, nadający się na telefony komórkowe – każdy element jest na pełną szerokość strony, kolejność jest taka jak w HTMLu.
Modyfikacje layoutu dla większych rozdzielczości, jak np. tablety
Powiedzmy że dla większych rozdzielczości (od 768px) chcemy, aby menu pojawiło się na górze, a panel boczny aby się zmieścił obok treści głównej. Dodajemy zatem CSS przy użyciu media queries
@media only screen and (min-width:768px) {
header {
order: 1;
}
nav {
order: 2;
}
article {
order: 3;
flex-basis: 70%;
}
aside {
order: 4;
flex-basis: 30%;
}
footer {
order: 5;
}
}
Teraz nasz layout powinien wyglądać tak jak na poniższym obrazku
I ponownie kilka słów wyjaśnienia:
- Zawarcie w CSS jakiegoś bloku w
@media only screen and (min-width:768px)
powoduje, że style nadane wewnątrz będą brane pod uwagę jedynie przy ekranach o minimalnej szerokości 768px. Jednak istotne jest to, że nie jest to odzwierciedleniem realnej rozdzielczości ekranu, a jedynie szerokości (w pikselach) interpretowanej przez CSS. Realną szerokość powinniśmy uzyskać mnożąc device-width przez pixel-ratio. Aby zobaczyć jakie masz wartości tych parametrów, możesz wejść na stronę mediaqueriestest.com - Parametr
order: 1
(i w kolejnych tagach kolejne numery) powoduje zmianę kolejności w wyświetlaniu elementów – w ten sposób ustawiamy właśnie, że nawigacja będzie na drugim miejscu, czyli pomiędzy nagłówkiem i treścią właściwą - Dodatkowo aby umieścić elementy obok siebie, musimy zmienić im
flex-basis
– tu podajemy 70% dla treści właściwej i 30% dla panelu bocznego – dzięki temu zmieszczą się obok siebie (przy uwzględnieniu box-sizing i padding ustawionych wcześniej) - Jeśli np. dla większych rozdzielczości (na desktopy) będziemy chcieli nawigację zwinąć do tzw. hamburgera, po prostu wypadnie z tradycyjnego flow flexboxa.
Krótkie podsumowanie parametrów flexbox
Nazwa parametru | Opis | Przykładowe wartości | Gdzie ustawiany |
---|---|---|---|
display | Ustawia sposób renderowania elementów wewnątrz danego taga | flex | kontener |
flex-direction | Określa w którą stronę (w pionie lub poziomie) będą ukłądane kolejne elementy wewnątrz kontenera | row, row-reverse, column, column-reverse | kontener |
flex-wrap | Określa, czy elementy mogą przechodzić do kolejnych wierszy | nowrap, wrap, wrap-reverse | element |
flex-basis | Ustawia szerokość (względną lub bezwzględną) dla danego elementu w kontenerze. | 100%, 50px, auto | element |
order | Umożliwia zmianę kolejności wyświetlania elementów flexboksa | element | |
flex-grow | Umożliwia rozszerzenie elementu, jeśli jest na to miejsce | 0 (domyślnie), 1 | element |
flex-shrink | Umożliwia zmniejszenie elementu, aby wiele zmieściło się obok siebie | 0, 1 (domyślnie) | element |
justify-content | Ustawia sposób układania elementów obok siebie, gdy ich wymiary nie wypełniają całej szerokości kontenera | flex-start, flex-end, center, space-between, space-around, space-evenly | kontener |
Użycie flexbox do pokazania galerii
Flexbox nadaje się nie tylko do stworzenia layoutu strony. Czasem mamy do pokazania długą listę elementów o tych samych wymiarach (np. miniatury obrazków w galerii) i chcielibyśmy, aby ich ilość w wierszu była zależna od szerokości ekranu.
Spróbujemy rozszerzyć nasz wcześniejszy przykład o taką właśnie listę elementów i tak ustawić CSS, aby dobrze się pokazywały zarówno na smartfonie (mała szerokość ekranu) jak i na dużym ekranie komputera. Zatem rozszerzamy nasz HTML do takiego
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Przykładowa galeria</title>
</head>
<body>
<header>Nagłówek</header>
<article>
<ul class="flexlist">
<li><div>Element 1</div></li>
<li><div>Element 2</div></li>
<li><div>Element 3</div></li>
<li><div>Element 4</div></li>
<li><div>Element 5</div></li>
<li><div>Element 6</div></li>
<li><div>Element 7</div></li>
<li><div>Element 8</div></li>
<li><div>Element 9</div></li>
<li><div>Element 10</div></li>
</ul>
</article>
<aside>Panel boczny</aside>
<nav>Nawigacja</nav>
<footer>Stopka</footer>
</body>
</html>
W wersji gdzie mamy elementy galerii, w liście zamiast taga <div> będziemy mieć oczywiście <img>.
Teraz podstawowe style dla powyższej listy, aby elementy wyświetlały się jeden pod drugim, na całej szerokości ekranu – czyli wersja na smartfony.
.flexlist {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
margin: 0;
padding: 0;
}
ul.flexlist {
list-style-type: none;
}
.flexlist > * {
flex-basis: 100%;
margin: 1ex;
min-width: 160px;
}
.flexlist > *:nth-child(3n) div {
background: #aaa;
}
.flexlist > *:nth-child(3n+1) div {
background: #ccc;
}
.flexlist > *:nth-child(3n+2) div {
background: #eee;
}
Oprócz używanych wcześniej elementów doszedł tutaj justify-content: space-between
. Powoduje on, że wolna przestrzeń pomiędzy elementami w jednym wierszu będzie wypełniona po równo. Nasza strona obecnie wygląda (na smartfonie) w taki sposób
Musimy dodać style dla wyższych rozdzielczości. Przyjmijmy, że od 768px szerokości będziemy wyświetlać elementy obok siebie, dając im minimalnie 160px i maksymalnie 240px. W tym celu dodajemy ponownie style w sekcji @media only screen and (min-width:768px)
:
.flexlist > * {
flex-basis: 200px;
}
Teraz przy szerokości ekranu około 900px nasza strona będzie mieściła 2 elementy obok siebie
Ale jak będziemy dysponować ekranem szerszym (np. 1024px), to zmieszczą się już 3 elementy obok siebie
Co najważniejsze, elementy będą „wyjustowane”, tzn. będą miały równe odstępy między sobą, oraz prawy i lewy margines również będą równej wielkości.
Kilka słów na koniec
Jak więc widać, flexbox daje duże możliwości określania layoutu, łącznie ze zmianą kolejności elementów, czy poprawnego skalowania do różnych rozdzielczości ekranu. Dzięki niemu strona stworzona przy użyciu flexbox będzie wyglądała poprawnie zarówno na smartfonie, tablecie jak i komputerze z dużym ekranem.
Jak chcesz przetestować swoją przeglądarkę, zobacz powyższy przykład flexbox.
Chociaż teoretycznie flexbox jest wspierany przez wszystkie popularne przeglądarki (IE11 nie jest już popularne), warto przetestować czy strona faktycznie wszędzie wyświetla się poprawnie.
Jeśli chcecie poczytać dokładniej (strony w języku angielskim) o flexbox, polecam strony do których sięgam w razie potrzeby (również pisząc ten krótki poradnik), czyli CSS-Tricks oraz caniuse.com.