24. CSS Flexbox

> Dodaj do ulubionych

Flexbox CSS, potocznie flexbox, to nowoczesna i uniwersalna metoda tworzenia responsywnych nieskomplikowanych układów elementów na stronach internetowych. Za jej pomocą w łatwy sposób można rozmieścić elementy na płaszczyźnie zarówno w pionie, jak i w poziomie.

CSS Flexbox jest jedną z kilku technologii tworzenia układów stron internetowych dostępnych w CSS. Oprócz niej istnieją jeszcze na przykład Układ wielokolumnowy CSS, CSS Grid czy techniki pozycjonowania elementów CSS. Każda z nich ma inne zastosowanie.

Metoda Flexbox odznacza się tym, że umożliwia łatwe projektowanie nieskomplikowanych układów rozmieszczenia treści na stronach za pomocą kompletnego zestawu narzędzi pozwalającego osiągnąć pożądany rezultat bez stosowania podejrzanych sztuczek.

Na przykład techniki pozycjonowania elementów CSS służą do ustalania położenia na stronie pojedynczych elementów, Układ wielokolumnowy CSS służy do rozmieszczania w kolumnach wybranych obszarów treści strony, aby ułatwić jej czytanie, upodabniając jej wygląd do łamów w gazecie. Z kolei układ CSS Grid to bardziej rozbudowana technologia, służąca do tworzenia rozbudowanych dwuwymiarowych układów.

Różne możliwości flexbox

Na ilustracji po prawej stronie widać różne sposoby rozmieszczenia kilku elementów na stronie. Z pomocą Flexbox wszystkie te aranżacje da się uzyskać bardzo łatwo — w każdym przypadku wystarczy zastosować jedną lub dwie własności z modułu Flexbox. Nie trzeba uciekać się do żadnych sztuczek, ani niczego zmieniać w kodzie HTML. Każdy z tych przykładów został wygenerowany z tego samego dokumentu.

Aby sprawnie i owocnie posługiwać się technologią CSS Flexbox, należy przyswoić sobie garść pojęć oraz nauczyć się używać kilku nieskomplikowanych własności. Zaczniemy od podstawowych terminów.

Podstawowe pojęcia

Oficjalna nazwa technologii potocznie nazywanej CSS Flexbox lub po prostu flexbox to CSS Flexible Box Layout. Nazwę tę można mniej więcej przetłumaczyć jako Układ pól elastycznych CSS. Słowo „elastyczny” w tej nazwie odnosi się do faktu, że układ ten oraz uczestniczące w nim elementy automatycznie dostosowują się do ilości dostępnej przestrzeni. Słowo pole oznacza wirtualny obszar tworzony w CSS przez każdy element na stronie internetowej (zobacz Model formatowania wizualnego CSS).

Element, którego zawartość jest rozmieszczona według zasad układu CSS Flexbox, nazywa się kontenerem flex lub kontenerem elastycznym (ang. flex container). Obowiązują w nim specjalne zasady układania elementów wzdłuż dwóch osi.

Każdy element, który jest bezpośrednim potomkiem (dzieckiem) kontenera flex, nazywa się jednostką flex lub jednostką elastyczną (ang. flex item). Jednostki flex to te elementy układu Flexbox, które są rozmieszczane na różne sposoby za pomocą specjalnych własności (często w tej roli występuje element div). Na poniższym rysunku kontener flex ma różowe tło, a jednostki flex są szare.

Kontener flex i jednostki flex

W układzie Flexbox nie obowiązują tradycyjne kierunki lewa, prawa, góra i dół, tylko elementy są rozmieszczane przez przeglądarkę wzdłuż dwóch wirtualnych osi — głównej i poprzecznej — kontenera flex.

Oś główna (ang. main axis) to podstawowa linia, wzdłuż której rozmieszczane są jednostki flex. Może ona być pozioma lub pionowa, zależnie od ustawienia własności flex-direction.

Jej początek (ang. main start) i koniec (ang. main end) określają rozmiar flex w wymiarze głównym (ang. main size) oraz kierunek układania jednostek flex (zawsze od początku do końca).

Zaś oś poprzeczna (ang. cross axis) jest prostopadła do osi głównej i także może być pozioma lub pionowa, zależnie od ustawienia osi głównej.

Jej początek (ang. cross start) i koniec (ang. cross end) wyznaczają rozmiar flex w wymiarze poprzecznym (ang. cross size) oraz kierunek układania jednostek flex w tym wymiarze (zawsze od początku do końca).

Na poniższym rysunku przedstawione są osie i pozostałe najważniejsze pojęcia układu CSS Flexbox.

wymiary i osie układu css flexbox
Wymiary i osie układu CSS Flexbox

Tworzenie kontenera flex

Aby utworzyć kontener flex (kontener elastyczny), należy wybranemu elementowi przypisać własność display o wartości flex lub inline-flex, które odpowiednio tworzą kontener blokowy i śródliniowy, np.:


.flex-container {
  display: flex;
}

Ta reguła CSS zamienia każdy element należący do klasy flex-container w kontener flex. W efekcie wszystkie elementy będące jego bezpośrednimi potomkami stają się jednostkami flex i zostają rozmieszczone według zestawu domyślnych ustawień układu Flexbox, które następnie można zmienić za pomocą odpowiednich własności.

Domyślnie jednostki flex są układane w jednym rzędzie, zaczynając od krawędzi początkowej osi głównej (od lewej strony w przypadku dokumentu w języku polskim), i nie ma między nimi odstępów. Jeśli kontener flex ma określoną szerokość i jednostki się w nim nie mieszczą, to przy domyślnych ustawieniach wychodzą poza jego granice.

Wyobraź sobie, że w dokumencie HTML znajduje się poniższy fragment kodu:


<div class="flex-container">
  <div class="flex-item"></div>
  <div class="flex-item"></div>
  <div class="flex-item"></div>
  <div class="flex-item"></div>
</div>

W arkuszu stylów z kolei znajdują się następujące reguły CSS:


.flex-container {
  display: flex;
  padding: 10px;
  background-color: #f8f5e9;
}
.flex-item {
  padding: 20px 30px;
  border: 1px solid black;
  background-color: #f1f1f1;
  font-size: 30px;
  font-weight: bold;
  font-family: sans-serif;
}

Kod ten tworzy kontener flex (.flex-container) z żółtawym tłem, zawierający cztery jednostki flex (.flex-item), które mają czarne obramowanie, szare tło i parę dodatkowych ustawień estetycznych, niezwiązanych z ich rozmieszczeniem w układzie.

Cztery jednostki flex domyślnie ułożone obok siebie bez odstępów

Za pomocą własności CSS Flexbox możemy zmienić rozmieszczenie tych elementów na różne sposoby.

Kierunek rozmieszczenia elementów

Domyślnie elementy w kontenerze flex są układane w jednym rzędzie od początku do końca osi głównej, której początek w przypadku dokumentów w języku polskim znajduje się na lewej krawędzi kontenera, a koniec — na prawej. Jeśli wolisz, aby zostały ułożone odwrotnie (od prawej do lewej), to możesz zmienić kierunek osi głównej za pomocą własności flex-direction, nadając jej wartość row-reverse (wartość row jest domyślna), np.:


flex-direction: row-reverse;

Własność ta określa kierunek osi głównej kontenera flex, a więc należy ją definiować właśnie dla kontenera, nie dla jego elementów potomnych.

Gdybyśmy dodali omawianą deklarację do wcześniejszej reguły z selektorem klasy .flex-container, to nasz kontener wyglądałby tak:

Efekt zmiany kierunku ułożenia elementów w układzie CSS Flexbox

Ponadto elementy można rozmieszczać także w kolumnie (czyli pionowo w przypadku dokumentów w języku polskim). Gdybyśmy zamiast wartości row-reverse w powyższym przykładzie własności flex-direction nadali wartość column, to efekt byłby taki:

Efekt zmiany kierunku ułożenia elementów na kolumnowe w układzie CSS Flexbox

Aby natomiast uzyskać kolumnę o odwróconej kolejności elementów, własności flex-direction należy przypisać wartość column-reverse, które układa elementy w kolumnach w odwrotnej kolejności.

Kontenery wielorzędowe

Za domyślne rozmieszczenie jednostek flex w jednym rzędzie odpowiada własność flex-wrap, której wartość początkowa to nowrap oznaczająca zakaz zawijania. Jeśli chcesz, aby jednostki były rozmieszczone w kilku rzędach, możesz zmienić ustawienie własności flex-wrap na wrap lub wrap-reverse.

Własność ta jest stosowana do kontenera flex a jej działanie jest dwojakie. Po pierwsze umożliwia rozmieszczenie zawartości w kilku rzędach, a po drugie określa kierunek osi poprzecznej kontenera (wartość wrap-reverse go odwraca).

Jej domyślna wartość to nowrap, która oznacza, że kontener ma być jednorzędowy. Dodatkowo przyjmuje wartość wrap, która tworzy kontener wielorzędowy, oraz wartość wrap-reverse, która tworzy kontener wielorzędowy o odwróconym kierunku osi poprzecznej (w przypadku dokumentu w języku polskim oś poprzeczna biegnie od góry, a po odwróceniu — od dołu).

Powiedzmy na przykład, że w regule dotyczącej klasy CSS flex-container usunęliśmy deklarację własności flex-direction, a w jej miejsce wstawiliśmy poniższą deklarację własności flex-wrap:

.flex-container {
  display: flex;
  flex-wrap: wrap-reverse;
  padding: 10px;
  background-color: #f8f5e9;
}

Ponadto w kodzie HTML dodaliśmy kilka jednostek flex, aby doprowadzić do utworzenia dwóch rzędów treści kontenera. Efekt tych działań jest następujący:

Dwa rzędy treści kontenera flex w odwróconej kolejności

Określanie kolejności elementów

W układzie CSS Flexbox w bardzo łatwy sposób można zmieniać kolejność renderowania elementów na ekranie bez zmieniania ich kolejności w kodzie źródłowym HTML. Służy do tego własność order, którą przypisuje się jednostkom flex (a także jednostkom grid) i która jako wartość przyjmuje liczbę całkowitą, np.:


.flex-item {
  order: 3;
}

Domyślna wartość tej własności to 0. Jeśli kilka elementów ma tę samą wartość, to tworzą one grupę porządkową, w której kolejność jest ustalana na podstawie kolejności w kodzie źródłowym. Spójrz na poniższy kod HTML:


<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
  <div class="flex-item">9</div>
</div>

Teraz za pomocą selektora pseudoklasy przemieszamy te elementy wizualnie.


.flex-container :nth-child(1),
.flex-container :nth-child(2),
.flex-container :nth-child(3) {
  order: 2;
}
.flex-container :nth-child(4),
.flex-container :nth-child(5),
.flex-container :nth-child(6) {
  order: 3;
}
.flex-container :nth-child(7),
.flex-container :nth-child(8),
.flex-container :nth-child(9)
  order: 1;
}

Efekt tych zabiegów jest widoczny na poniższym zrzucie ekranu.

Efekt zmiany kolejności grup elementów

Własność order przyjmuje także wartości ujemne, co może przydać się w sytuacji, gdy chcemy przenieść jeden element na początek jakiejś grupy.

Wyrównanie wzdłuż osi głównej

Jeśli jednostki flex znajdujące się w kontenerze flex nie zajmują całej dostępnej przestrzeni wzdłuż osi głównej (w poziomie w przypadku domyślnych ustawień w dokumencie w języku polskim), to za pomocą własności justify-content można zdecydować, jak powinno wyglądać ich rozmieszczenie.

Własność tę przypisuje się kontenerowi flex i ma ona dość pokaźny zasób wartości, które mogą być używane także w innych rodzajach układu CSS. Poniżej przedstawiam listę chyba najczęściej używanych, które zostały zdefiniowane w specyfikacji CSS Flexbox. Dokładny opis wszystkich z nich znajduje się na stronie Własność CSS justify-content.

  • flex-start — wyrównanie do początku osi głównej (w uproszczeniu do lewej)
  • flex-end — wyrównanie do końca osi głównej (w uproszczeniu do prawej)
  • center — wyrównanie do środka
  • space-between — równomierne rozmieszczenie elementów od krawędzi do krawędzi
  • space-around — równomierne rozmieszczenie elementów z dodatkiem połowy odstępu między krawędzią a pierwszym i ostatnim elementem

Poniższa ilustracja przedstawia różnice między tymi ustawieniami:

Przykłady różnych metod wyrównania elementów w poziomie w CSS Flexbox

Wyrównanie wzdłuż osi poprzecznej

W technologii CSS Flexbox do rozmieszczania elementów wzdłuż osi poprzecznej (standardowo w pionie w przypadku dokumentów w języku polskim) służą trzy własności: align-content, align-items oraz align-self. Pierwsza kontroluje rozmieszczenie linii elementów w kontenerze, a dwie pozostałe odnoszą się do indywidualnych elementów.

Wyrównanie linii elementów

Własność align-content wyrównuje linie jednostek flex wzdłuż osi poprzecznej kontenera flex, gdy dostępny jest nadmiar miejsca w tym wymiarze. To oznacza, że własność tę należy definiować dla wielorzędowych kontenerów flex, a więc takich, które mają własność flex-wrap ustawioną na wrap lub wrap-reverse. Spójrz na poniższy rysunek, na którym są pokazane linie jednostek flex w kontenerze.

Kontener flex z dwiema liniami jednostek flex

Przy domyślnym ustawieniu własności align-content (stretch) jednostki flex są równomiernie rozciągane na całą dostępną przestrzeń wzdłuż osi poprzecznej. Można to zmienić, przypisując tej własności inną wartość.

Własność align-content przyjmuje wiele wartości. Poniżej przedstawiam niektóre z najczęściej używanych, które są zdefiniowane w specyfikacji CSS Flexbox. Jeśli chcesz dokładnie poznać wszystkie, ich opis znajdziesz na stronie Własność CSS align-content.

  • flex-start — wyrównanie do początku osi poprzecznej kontenera
  • flex-end — wyrównanie do końca osi poprzecznej kontenera
  • center — wyrównanie do środka
  • space-between — równomierne rozmieszczenie elementów od krawędzi do krawędzi
  • space-around — równomierne rozmieszczenie elementów z dodatkiem połowy odstępu między krawędzią a pierwszym i ostatnim elementem

Zwróć uwagę, że ten zestaw wartości jest taki sam, jak w przypadku własności justify-content. To nie przypadek — własność align-content jest odpowiednikiem własności justify-content, tylko dla osi poprzecznej. Poniżej na przykład pokazany jest efekt zastosowania ustawienia space-around.

.flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: space-around;
}

Efekt:

Efekt zastosowania ustawienia space-around do własności align-content

Wyrównanie indywidualnych elementów

Opisana powyżej własność align-content służy do określania wyrównania wzdłuż osi poprzecznej całych linii jednostek flex w kontenerze flex, w związku z czym odnosi się ona do kontenera.

Natomiast własność align-self pozwala na określenie sposobu wyrównania indywidualnych jednostek flex w kontenerze, więc definiuje się ją dla wybranych jednostek flex, a nie dla całego kontenera. Spójrz na poniższy zrzut ekranu:

Jednostka flex o indywidualnie zmienionym wyrównaniu

Przy domyślnych ustawieniach jednostki flex w kontenerze flex rozciągają się na całą dostępną przestrzeń wzdłuż osi poprzecznej. Na rysunku domyślne ustawienia mają elementy 1, 3 i 4. Natomiast elementowi 2 została przypisana własność align-self o wartości center, dlatego został on wyśrodkowany na osi poprzecznej.


.flex-container :nth-child(2) {
  align-self: center;
}

Własność align-self odnosi się do indywidualnych elementów, więc gdybyśmy chcieli wyśrodkować wszystkie jednostki flex w danym kontenerze, musielibyśmy ją zdefiniować dla każdej z nich.

Aby zaoszczędzić pracy projektantom, stworzono więc dodatkowo własność align-items, która ma zastosowanie do kontenera i działa identycznie, jak align-self, tylko odnosi się do wszystkich jednostek flex w danym kontenerze.

To właśnie jej wartość domyślna (stretch) jest odpowiedzialna za początkowe rozciągnięcie wszystkich jednostek flex na całą dostępną przestrzeń w kontenerze wzdłuż osi poprzecznej. Inaczej mówiąc, własność align-items służy do określania domyślnego rozmieszczenia elementów flex wzdłuż osi poprzecznej kontenera.

Ponadto własności align-items i align-self, w odróżnieniu od własności align-content, działają zarówno w kontenerach jedno-, jak i wielowierszowych.

Proporcje rozmiaru jednostek flex

Choć nazwa CSS Flexbox oznacza „Układ pól elastycznych CSS”, do tej pory nie było jeszcze mowy o czymkolwiek, co można by było określić w ten sposób. A przecież elastyczność jest właśnie solą tego rodzaju układu.

Pora nadrobić tę zaległość i dowiedzieć się, na czym polega elastyczność Flexboksa. Pola w układzie Flexbox CSS rzeczywiście są elastyczne już domyślnie, tylko jeszcze nie korzystaliśmy z tej ich cechy. Do sterowania ich elastycznością służą cztery własności Flexbox: trzy indywidualne i jedna zbiorcza, która pozwala na ustawianie wartości dla nich wszystkich w jednej deklaracji. Oto te własności:

flex-basis
Określa bazowy rozmiar jednostki flex, bazę flex (ang. flex basis), która stanowi jej rozmiar początkowy w wymiarze głównym. Rozmiar ten jest następnie brany pod uwagę przy dystrybuowaniu przestrzeni wolnej według współczynników elastyczności, które są reprezentowane przez własności flex-grow i flex-shrink.
flex-grow
Jest to pierwszy z dwóch współczynników elastyczności. Określa proporcję zwiększania danej jednostki flex względem pozostałych znajdujących się w tym samym kontenerze, czyli tzw. współczynnik zwiększania flex (ang. flex grow factor).
flex-shrink
Jest to drugi z dwóch współczynników elastyczności. Określa proporcję zmniejszania danej jednostki flex względem pozostałych znajdujących się w tym samym kontenerze, czyli tzw. współczynnik zmniejszania flex (ang. flex shrink factor).
flex
Służy do definiowania wartości dla wszystkich powyższych własności. Kolejność powinna być następująca: flex: flex-grow flex-shrink flex-basis. Szczegóły składni tej własności są opisane na stronie Własność CSS flex.

Rozmiar bazowy

Rozmiar bazowy jednostki flex jest ustawiany przez własność flex-basis, która przyjmuje takie same wartości, jak własności width i height, oraz dodatkowo przyjmuje słowo kluczowe content.

Jak wskazuje nazwa, rozmiar ten stanowi bazę do obliczenia ostatecznego rozmiaru jednostki flex w wymiarze głównym. Jeśli własność flex-basis ma wartość auto (jest to jej wartość początkowa), to rozmiar bazowy elementu zostaje ustalony na podstawie ustawień innych własności, np. width, a w przypadku ich braku — na podstawie treści.

Jeśli żadna inna własność nie określa rozmiaru jednostki flex w wymiarze głównym, to jest on określany na podstawie jej treści. W takim przypadku rozmiar ten jest równy najmniejszej możliwej szerokości pola elementu, jaka wystarcza do objęcia całej jego zawartości bez zawijania. Fachowo nazywa się to maksymalnym rozmiarem treści (ang. max-content size). A w lekkim uproszczeniu można powiedzieć, że jest to rozmiar otrzymany po „obkurczeniu” elementu na jego treści, jak torebki foliowej na produkcie po odessaniu z niej powietrza.

Wyobraź sobie na przykład, że w dokumencie HTML znajduje się taki kod:


<div class="flex-container">
  <div class="flex-item">Gdyby</div>
  <div class="flex-item">kózka</div>
  <div class="flex-item">nie</div>
  <div class="flex-item">skakała</div>
</div>

Poniżej znajduje się fragment arkusza stylów zastosowanego do tego dokumentu (część nieistotnych ustawień estetycznych usunąłem dla uproszczenia):


.flex-container {
  display: flex;
}
.flex-item {
  border: 1px solid black;
  margin: 5px;
}

W oknie przeglądarki wygląda to tak:

Przykład obkurczenia elementu do rozmiaru jego treści

Każda jednostka ma jednopikselowe obramowanie, które pokazuje, że zgodnie z powyższym opisem, jednostki flex przy braku jakichkolwiek innych ustawień rozmiaru, przyjęły maksymalny rozmiar treści.

Ta wartość (obliczona wewnętrznie przez przeglądarkę) będzie stanowiła bazę flex przy dalszych obliczeniach związanych z ustawieniami własności flex-grow i flex-shrink.

Jeśli natomiast własności flex-basis nadamy wartość liczbową z jednostką długości CSS, np. 200px, 8em czy 6rem, to wtedy ta wartość będzie stanowiła bazę flex i będzie ona traktowana jako rozmiar minimalny. Gdyby treść jednostki wymagała więcej miejsca, to jednostka ta zostanie odpowiednio rozszerzona i to ta ostateczna wartość będzie używana jako rozmiar bazowy.

Z kolei wartość procentowa jest obliczana na podstawie rozmiaru kontenera zawierającego daną jednostkę flex. Jeżeli na przykład kontener będzie miał 1000 pikseli szerokości, to wartość 50% będzie oznaczała 500 pikseli.

Ponadto istnieje jeszcze słowo kluczowe content, które powoduje, że rozmiar jednostki flex jest równy maksymalnemu rozmiarowi jej treści (to słowo kluczowe dodatkowo uwzględnia ustawienia współczynnika kształtu za pomocą własności aspect-ratio) bez względu na ustawienie innych własności, np. width.

Kiedy przeglądarka określi już rozmiar bazowy wszystkich jednostek flex, przechodzi do ustalenia ich ostatecznego rozmiaru, który uwzględnia współczynniki zwiększania i zmniejszania zdefiniowane przez własności flex-grow i flex-shrink.

Ustalanie to polega na „dodaniu” każdej jednostce odpowiedniej ilości przestrzeni wolnej, która pozostała w kontenerze po nadaniu jednostkom rozmiarów bazowych. Słowo „dodaniu” umieściłem w cudzysłowie, ponieważ przestrzeń wolna może być dodatnia lub ujemna, a więc w niektórych przypadkach tak naprawdę rozmiar elementów będzie zmniejszany, a nie zwiększany.

Dodatnia i ujemna przestrzeń wolna

W technologii CSS Flexbox wyróżnia się dwa rodzaje przestrzeni wolnej: dodatnią i ujemną. Zrozumienie tych prostych pojęć ma kluczowe znaczenie dla dokładnego zrozumienia działania własności flex-grow i flex-shrink.

Dodatnia przestrzeń wolna (ang. positive free space) to przestrzeń w kontenerze, która nie została przydzielona żadnej jednostce flex. Inaczej mówiąc, jest to puste miejsce w kontenerze. Spójrz na poniższą ilustrację.

Ilustracja dodatniej przestrzeni wolnej w Flexbox CSS

Na rysunku tym kontener flex o szerokości 800 pikseli zawiera cztery jednostki flex o rozmiarze bazowym 100 pikseli każda, co oznacza, że w sumie zajmują one 400 pikseli. W związku z tym w kontenerze pozostaje 400 pikseli dodatniej przestrzeni wolnej, która następnie zostanie rozdzielona między jednostki zgodnie z ich ustawieniami własności flex-grow.

Natomiast ujemna przestrzeń wolna (ang. negative free space) to ilość brakującego miejsca dla jednostek flex w kontenerze. Spójrz na poniższy rysunek.

Ujemna przestrzeń wolna w CSS Flexbox

Na tym rysunku kontener flex o szerokości 300 pikseli zawiera cztery jednostki flex o rozmiarze bazowym 100 pikseli każda, co oznacza, że w sumie zajmują one 400 pikseli. W związku z tym powstaje niedomiar o wartości 100 pikseli (-100px na rysunku) — to właśnie nazywa się ujemną przestrzenią wolna.

Kiedy przeglądarka będzie renderować te elementy, to każdej jednostce odejmie odpowiednią część szerokości zgodnie z ustawieniami własności flex-shrink, tak aby wszystkie jednostki zmieścić w kontenerze.

Pora przyjrzeć się własnościom flex-grow i flex-shrink. Zaczniemy od współczynnika zwiększania, czyli własności flex-grows.

Proporcjonalne zwiększanie elementów

Własność flex-grow działa tylko wtedy, gdy w kontenerze występuje dodatnia przestrzeń wolna, czyli gdy suma rozmiarów bazowych wszystkich znajdujących się w nim jednostek flex jest mniejsza od jego rozmiaru w wymiarze głównym.

Własność ta definiuje współczynnik zwiększania, nie konkretną wartość, wybranej jednostki względem pozostałych jednostek. W przenośni można powiedzieć, że określa ona, ile kawałków reszty tortu po pierwszym podziale (wolnej przestrzeni) przypadnie każdemu uczestnikowi przyjęcia (jednostce flex).

Powiedzmy, że na przyjęciu są cztery osoby. Prezes, kierownik oraz dwóch zwykłych pracowników. Prezes jest najważniejszy, więc należy mu się trzy razy więcej kawałków niż zwykłemu pracownikowi. Natomiast kierownik jest dwa razy ważniejszy od zwykłego pracownika.

W związku z tym resztę tortu podzielimy na 7 równych części: trzy z nich damy prezesowi, dwie damy kierownikowi, a po jednej damy każdemu z pracowników. Dokładnie tak działa własność flex-grow. Spójrz na poniższy przykład kodu CSS, który odzwierciedla opisaną sytuację:


.flex-container {
  display: flex;
  width: 800px;
}
.flex-container > * {
  flex-basis: 100px;
}
.flex-item1 {
  flex-grow: 3;
}
.flex-item2 {
  flex-grow: 2;
}
.flex-item3, .flex-item4 {
  flex-grow: 1;
}

W tym kodzie „prezesem” jest element flex-item1, kierownikiem jest flex-item2, a pracownikami są flex-item3 i flex-item4. Selektor dziecka > w połączeniu z selektorem uniwersalnym * nadaje wszystkim jednostkom flex rozmiar bazowy 100 pikseli. To znaczy, że w sumie jednostki te zajmują 400 pikseli, więc do podziału zostaje jeszcze kolejne 400 pikseli.

Do rozdzielenia potrzebujemy 7 równych części, więc dzielimy 400 pikseli przez 7, co daje nam w przybliżeniu 57 pikseli. Taki jest rozmiar jednego kawałka. Teraz każdemu uczestnikowi przyjęcia dajemy tyle kawałków, ile mu się należy:

  • Prezes: 3 × 57 = 171 pikseli
  • Kierownik: 2 × 57 = 114 pikseli
  • Pracownik: 1 × 57 = 57 pikseli

Mniej więcej po tyle dodatkowo dostanie każdy z uczestników spotkania (każda jednostka flex). Czyli ostatecznie ich rozmiary wyniosą:

  • Prezes: 100 pikseli + 171 pikseli = 271 pikseli
  • Kierownik: 100 pikseli + 114 pikseli = 214 pikseli
  • Pracownik: 100 pikseli + 57 pikseli = 157 pikseli

Przy domyślnych ustawieniach własność flex-grow jest wyłączona (ma wartość 0), co oznacza, że jednostki flex pozostają przy swoim rozmiarze bazowym. Dlatego nasze elementy wyglądałyby tak, jak na ilustracji przedstawiającej dodatnią przestrzeń wolną.

Natomiast po dodaniu własności flex-grow, jak pokazałem powyżej, rozmiary jednostek flex zmienią się na zgodnie z przedstawionymi obliczeniami. Spójrz na poniższy rysunek.

Rozmiary po zastosowaniu flex-grow

Opisana zasada proporcjonalnego podziału obowiązuje w każdej sytuacji, także gdy własność flex-basis ma wartość auto lub w ogóle nie została zdefiniowana (czyli ma wartość początkową auto, w którym to przypadku używa wartości max-content), gdy zamiast niej ustawiono szerokość jednostek flex za pomocą własności width itd.

We wszystkich tych przypadkach sposób postępowania przeglądarki jest taki sam:

  1. Sprawdzenie, czy rozmiar główny jednostek flex jest określony wprost i wykorzystanie go, jeśli tak.
  2. Jeśli nie, obliczenie rozmiaru głównego jednostek flex na podstawie rozmiaru ich treści.
  3. Obliczenie rozmiaru dodatniej przestrzeni wolnej w kontenerze flex, która może być określona wprost, np. przez własność width, albo na podstawie innych czynników, takich jak szerokość okna itp.
  4. Proporcjonalne rozdzielenie przestrzeni wolnej między jednostki na podstawie ustawień ich własności flex-grow.

Proporcjonalne zmniejszanie elementow

Własność flex-shrink jest „lustrzanym odbiciem” własności flex-grow — zamiast rozdzielać wolną przestrzeń między jednostki flex, zmniejsza je proporcjonalnie, aby wszystkie w całości się zmieściły w kontenerze.

W ramach przykładu przyjrzymy się poniższemu kontenerowi elastycznemu:


<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
</div>

Do niego dodajemy następujący arkusz stylów:


.flex-container {
  display: flex;
  width: 300px;
}
.flex-container > * {
  flex-basis: 100px;
}
.flex-item1 {
  flex-shrink: 3;
}
.flex-item2 {
  flex-shrink: 2;
}
.flex-item3, .flex-item4 {
  flex-shrink: 1;
}

Obliczenia ostatecznych rozmiarów wyglądają bardzo podobnie, jak w przypadku własności flex-grow.

  1. Sprawdzamy szerokość kontenera — tu wynosi ona 300 pikseli i została ustawiona przez własność width.
  2. Sprawdzamy rozmiar główny jednostek flex — tu wynosi on 100 pikseli i został ustawiony przez własność flex-basis.
  3. Obliczamy sumę rozmiarów jednostek flex — otrzymujemy 400 pikseli (4 × 100).
  4. Obliczamy ilość ujemnej przestrzeni wolnej, która jest różnicą rozmiaru głównego kontenera flex i sumy rozmiarów głównych jednostek flex — 300 pikseli − 400 pikseli = −100 pikseli.
  5. Dzielimy ilość brakującego miejsca przez liczbę potrzebnych nam „kawałków”, czyli przez 7, tak jak w poprzednim przykładzie, bo suma wartości własności flex-shrink wynosi 3 + 2 + 1 + 1 = 7.
  6. Obliczamy szerokość jednego kawałka: 100 pikseli ÷ 7 ≈ 14 pikseli.
  7. Każdemu elementowi odejmujemy tyle razy 14 pikseli, ile wynosi jego wartość flex-shrink.

W efekcie elementy przyjmują następujące rozmiary w wymiarze głównym:

  • Element 1: 100 pikseli − 3 × 14 pikseli = 58 pikseli
  • Element 2: 100 pikseli − 2 × 14 pikseli = 72 piksele
  • Elementy 3 i 4: 100 pikseli − 1 × 14 pikseli = 86 pikseli

Spójrz na poniższy rysunek, który przedstawia efekt działania opisywanych ustawień.

Efekt zastosowania własności flex-shrink w Flexbox

Odstępy między jednostkami

Na koniec pokażę Ci, jak ustawiać odstępy między wierszami i kolumnami jednostek flex. Własności, które do tego służą, nie należą do modułu CSS Flexbox, tylko do bardziej ogólnego modułu o nazwie CSS Box Alignment, który zawiera definicje własności obsługiwanych także w innych technologiach CSS, takich jak Układ wielokolumnowy CSS, czy układ CSS Grid.

Oto one:

  • row-gap — określa odstęp między rzędami jednostek
  • column-gap — określa odstęp między kolumnami jednostek
  • gap — własność zbiorcza obejmująca dwie poprzednie

Każda z tych własności jako wartość przyjmuje liczbę z jednostką długości CSS i powinna być stosowana do kontenera flex. Ich ustawienia należy traktować jako odstęp minimalny, a nie sztywną wartość, ponieważ niektóre własności Flexbox CSS, np. align-content, mogą ten odstęp zwiększyć.

Powiedzmy, że mamy poniższy fragment dokumentu HTML, który już widzieliśmy:


<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
</div>

W arkuszu stylów znajdują się następujące dotyczące go reguły CSS:


.flex-container {
  display: flex;
  width: 350px;
  flex-wrap: wrap;
  gap: 20px;
  background-color: #f8f5e9;
}
.flex-container > * {
  padding: 30px;
  border: 1px solid black;
  background-color: #f1f1f1;
  font-size: 22px;
  font-weight: bold;
  font-family: sans-serif;
}

W przeglądarce będzie to wyglądało tak:

Przykład działania własności gap

A gdybyśmy usunęli deklarację własności gap z reguły klasy .flex-container, otrzymalibyśmy taki wynik:

Efekt usunięcia własności gap

Oczywiście odstępy między jednostkami flex można ustawiać także za pomocą własności z rodziny margin, ale własności gap zostały stworzone dokładnie do tego celu i są w tej sytuacji poręczniejsze. Na przykład określają odstęp tylko między jednostkami flex, natomiast własność margin ustawia odstęp także między elementami a krawędziami kontenera.

Jajko z dzwonkiem

Podoba Ci się ta strona?

Pomóż nam się rozwijać, wykupując płatne konto. Dzięki temu będziemy mogli tworzyć dla Ciebie jeszcze więcej ciekawych treści, a Ty pozbędziesz się reklam.

Autor: Łukasz Piwko