Flexible Boxes - ikona wpisu

WTF is… Flexible box

WTF is… to seria artykułów o nowościach tak gorących, że nikt jeszcze o nich nie słyszał. A nawet jeśli słyszał, to zapewne jeszcze nie korzystał. ;)

Niektórzy z Was na zdjęciu tytułowym rozpoznają charakterystyczny layout Pinteresta. Charakterystyczne są w nim dwie rzeczy: cholernie dobrze wygląda i cholernie trudno taki efekt osiągnąć. A ściślej mówiąc… Cholernie trudno BYŁO taki efekt osiągnąć! Z pomocą nadchodzi nowość w CSS: Flexible boxes, czyli po naszemu – elastyczne boksy.

Elastyczne boksy to sposób na otrzymanie siatki (choć to złe słowo, bo boksy bynajmniej nie muszą być równe) boksów. Zapewne do tej pory większość osób budowała taką siatkę za pomocą zaaplikowania stylu display: inline-block, po czym mozolnie liczyła odstępy, usuwała boczne marginesy z pierwszego i ostatniego elementu w wierszu używając do tego celu pseudoselektorów nth-child… Innymi słowy – każda taka siatka wymagała ogromu pracy, a im więcej elementów takiej siatki – tym większy ból głowy (przede wszystkim dnia następnego).

Flexible Boxes - layout

Z elastycznymi boksami wszystko staje się proste. Parametry CSS w layoucie opartym na elastycznych boksach przyporządkowujemy dwóm rodzajom elementów: elementowi-rodzicowi (na obrazku powyżej – niebieski) i elementom-dzieciom (różowe).

Parametry CSS dla rodzica

display: flex

Pierwszy i najważniejszy parametr. Przypisanie go elementowi-rodzicowi spowoduje, że wszystkie elementy będące bezpośrednimi potomkami elementu-rodzica zdefiniowane zostają jako elastyczny boks. Tak, wiem, to zdanie trzeba przeczytać powoli kilka razy, ale to naprawdę proste. Efekt użycia tego parametru jest podobny do użycia display: inline-block na elementach-dzieciach – szerokość elementów-dzieci przestaje wynosić 100% i wyświetlane są one w jednej linii.

flex-direction: row | row-reverse | column | column-reverse

No właśnie, w jednej linii… Domyślna wartość parametru flex-direction to row, ale nic nie stoi na przeszkodzie, by zmienić kierunek wyświetlania elementów. Gdy ustawimy jego wartość na row-reverse, elementy zaczną wyświetlać się od prawej do lewej, jeśli column – od góry do dołu, jeśli column-reverse – od dołu do góry.

flexbox2column-reverse w praktyce.

flex-wrap: nowrap | wrap | wrap-reverse

Parametr flex-wrap pozwala nam kontrolować zawijanie się elementów do następnego wiersza (tudzież następnej kolumny, jeżeli bawiliśmy się wyżej opisanym parametrem).

  • Wartość nowrap to domyślny, jednolinijkowy układ boksów,
  • wartość wrap to zawijanie do następnego wiersza,
  • wrap-reverse zawija boksy do następnego wiersza, ale wiersze te ustawia w kolejności odwrotnej.

flexbox3wrap-reverse w praktyce. Nikt nie wie, po co, no ale – można.

justify-content: flex-start | flex-end | center | space-between | space-around

No i zaczyna się spijanie śmietanki!

  • Wartości flex-start, flex-end i center wyrównają boksy odpowiednio do lewej strony, prawej strony i do środka,
  • space-between rozrzuci boksy po dostępnej przestrzeni zostawiając między nimi równe odstępy,
  • space-around rozrzuci boksy po dostępnej przestrzeni zostawiając między nimi oraz krawędziami równe odstępy.

flexbox4Góra: space-around, dół: space-between.

Parametry CSS dla elementów-dzieci

order: <liczba>

Nadając ten parametr danemu elementowi i podając za wartość jakąś liczbę, możemy nadpisać domyślną kolejność elementów.

Ale uwaga! Ponieważ domyślną wartością jest 0, to przypisując temu parametrowi danego elementu jakąkolwiek liczbę wyższą niż 0, ustawiamy go na końcu listy. Dopiero gdy wszystkie elementy mają nadany parametr order, mamy pełną kontrolę nad kolejnością elementów.

flex-grow: <liczba>

Gdy nie zdecydowaliśmy się na podanie wielkości elementów, przeglądarka wyświetli je w takiej sytuacji jako równe. Parametr flex-grow umożliwia nam jednak zmianę tego zachowania. Wartość liczbowa tego parametru jest niczym innym jak proporcją wielkości tego elementu względem pozostałych. Brzmi zawile? Przepraszam, już ilustruję:
flexbox5
W tym wypadku elementowi 3 przypisałem flex-grow: 1, a elementowi 4 flex-grow: 2.
Domyślną wartością parametru flex-grow jest 0, więc elementy 1, 2, 5 oraz 6 ścisnęły się do minimum określonego przeze mnie parametrem min-width.
Element 3 otrzymał 1/3 pozostałego miejsca w danym wierszu, a element 4 otrzymał 2/3 pozostałego miejsca, zgodnie z proporcjami zapisanymi w ww. parametrze.

align-self: auto | flex-start | flex-end | center | baseline | stretch

Nie zawsze będziemy mieli do czynienia z elementami o równej wysokości. W takiej sytuacji pod niższymi elementami z danej linii pozostanie puste miejsce. align-self służy nam do odpowiedniego ułożenia pionowego elementów w danej linii.

  • Wartość flex-start umieści element możliwie blisko początku wiersza/kolumny (przy domyślnych ustawieniach można byłoby napisać: najbliżej góry wiersza, ale nie zapominajmy, że w układzie boksów można nieźle namieszać),
  • flex-end umieści element możliwie blisko końca wiersza/kolumny,
  • center – wycentruje element,
  • baseline – wyrówna element do linii bazowej,
  • stretch – rozciągnie element do maksymalnej wielkości, od początku do końca wiersza/kolumny.

Przykład:

flexbox6
W tym wypadku element 5 nieco rozepchał się w wierszu. Element 4 otrzymał parametr align-self: center, dlatego ustawił się na środku linii. Element 6 otrzymał parametr align-self: flex-end, dlatego znajduje się maksymalnie nisko.

Wartości parametru align-self można użyć również w parametrze align-items nadawanym rodzicowi. Parametr align-items odnosi się wtedy do wszystkich elementów-dzieci, za wyjątkiem tych, które dostały „ważniejsze” align-self.

 

Zanim jednak pobiegniecie wykorzystywać elastyczne boksy w swoich komercyjnych projektach, nie zapomnijcie o tym, że w 100% wspierają go dopiero Chrome 29, Firefox 28 i Internet Explorer 11. Seria WTF is… ma na celu pokazanie Ci, jak kodować będzie się za rok. Gdy rok minie, inni będą dopiero raczkować, Ty z nowinkami w CSS-ie będziesz czuł(a) się jak w domu. :)

Uff… To mój pierwszy artykuł tego typu. Bardzo proszę Was o informację zwrotną: czy podobało Wam się? Czy coś jest niejasne i należałoby wytłumaczyć lepiej? Z góry bardzo, bardzo dziękuję za każdą Waszą opinię! :)