Tytuł po angielsku, gdyż nie wiedziałem jak to się po naszemu nazywa, ani jak to ładnie na polski przetłumaczyć: "elastyczny model pudełkowy"? Za wszelkie podpowiedzi ładnie podziękuję. Dodatkowo, jeśli gdzieś się pomyliłem, to będę wdzięczny za poprawki - nie jestem ekspertem, staram się jedynie przyswoić wiedzę na dany temat i rezultatami podzielić się z Wami.

Na Ferrante zakończył się konkurs, w którym zadanie polegało na skonstruowaniu układu trójkolumnowego z dodatkowymi warunkami, szczegóły we wspomnianym wpisie. Rozwiązanie znaleźć można tutaj. Wszystko pięknie ślicznie, gratulacje i tak dalej, ale patrząc w kod źródłowy, to połowy nie rozumiałem. Niewiedza rzeczą ludzką, więc postanowiłem się doedukować.

Czym jest Flexible box model w CSS3?

Flexible box model to nic innego, jak dodatkowy sposób wyświetlania elementów na stronie. Kojarzycie display: inline i display: block? Teraz do dyspozycji mamy jeszcze display: box, co daje nam większą kontrolę nad wyglądem i zachowaniem się elementów w zależności od tego co zawierają, w jakiej rozdzielczości ekranu są wyświetlane itp itd. Może to brzmieć trochę tajemniczo, więc postaram się to dokładniej opisać i przedstawić konkretne przykłady.

display: box

Ustawienie tej własności pozwala nam rozpocząć zabawę z flexible box model.

box-flex

Przyjmuje wartości całkowite dodatnie, które odpowiadają za stosunek zajmowanego miejsca przez poszczególne elementy. Dzięki temu elementy stają się elastyczne i dostosowują się do całkowitego dostępnego dla nich miejsca. Dynamiczne dodanie kolejnych elementów nie popsuje struktury (tak jak w przypadku procentów), ponieważ wielkość poszczególnych elementów dostosowuje się automatycznie do dostępnego miejsca.

box-orient

Manipulując parametrami horizontal i vertical możemy decydować o rozmieszczeniu elementów, pierwszy układa je w poziomie, drugi w pionie.

box-direction

Dzięki tej własności możemy skorzystać z parametru reverse, który powoduje odwrócenie kolejności elementów.

box-ordinal-group

Grupuje elementy i nadaje im priorytety, dzięki czemu grupa z niższą wartością znajdzie się wyżej w strukturze, niż ta z wyższą.

box-pack

Ta własność pozwala rozlokować dany element w poziomie, do dyspozycji mamy start, end, justify i center.

box-align

Ta własność pozwala rozlokować dany element w pionie, do dyspozycji mamy start, end, center, baseline i stretch.

Przykłady

Czas pokazać kilka przykładów, dla lepszego zrozumienia teorii. Pamiętajcie, że w przykładach CSS3 użyte są definicje bez przedrostków, a więc widząc box-flex dla pełnego wsparcia Firefoxa oraz Safari należy używać ich odpowiednich przedrostków, a więc -moz-box-flex oraz -webkit-box-flex. Internet Explorer oczywiście odpada. Wszystkie przykłady opierają się o ten sam szkielet HTML:
<div class="example">
<div>box 1</div>
<div>box 2</div>
<div>box 3</div>
</div>

Przykład 1


Przykład 1

Do stworzenia takiego przykładu wystarczyła poniższa definicja w CSS:
#example1 {
display: box;
box-orient: horizontal;
}
#example1 > div:nth-child(1) {
box-flex: 2;
}
#example1 > div:nth-child(2) {
box-flex: 1;
}
#example1 > div:nth-child(3) {
box-flex: 1;
}

Najpierw główny kontener dostał display: box (co będzie się pojawiać przy każdym kolejnym przykładzie), a także box-orient: horizontal, dzięki czemu elementy ułożone są poziomo. Bez użycia float, bez potrzeby używania clear. Kolejne linie to użycie box-flex, dzięki czemu elementy zaczną wypełniać całą dostępną przestrzeń. W tym przypadku szerokość wynosi 600px, natomiast box-flex dla kolejnych elementów przyjmuje wartość 2, 1 i 1. W sumie daje to podział na 4, a więc pierwszy element będzie miał długość 2/4 * 600px = 300px. Pozostałe dwa elementy będą miały długość po 150px według wzoru 1/4 * 600px. Jeśli zmienimy szerokość na 800px, to wtedy wszystkie elementy będą mnożone przez tą wartość według wzoru 1/4 * 800px = 200px. Jeśli dodamy kolejny element o box-flex: 1, to będziemy dzielić dostępną szerokość przez 5, według wzoru 1/5 * 800px = 160px.

Przykład 2


Przykład 2

Tu jest już trochę ciekawiej, jeden z elementów ma stałą szerokość wyrażoną w pikselach:
#example2 {
display: box;
box-orient: horizontal;
}
#example2 > div:nth-child(1) {
box-flex: 1;
}
#example2 > div:nth-child(2) {
box-flex: 4;
}
#example2 > div:nth-child(3) {
width: 100px;
}

Początek jest ten sam, mamy elementy ułożone poziomo. Następnie pojawia się zapis podobny do tego z pierwszego przykładu, jedynie stosunek długości dwóch pierwszych elementów jest inny. Różnica polega na trzecim elemencie, który ma długość 100px i nie korzysta z box-flex. Jaką szerokość będą miały poprzednie dwa elementy? Od całkowitej szerokości 600px odejmujemy element ze stałą 100px i dzielimy pozostałą szerokość na dostępne elementy. Pierwszy element będzie miał szerokość 1/5 (bo 1 + 4) * 500px (bo 600px - 100px) = 100px, natomiast drugi 4/5 * 500px = 400px.
To w teorii, bo w praktyce, mierząc dokładnie szerokość poszczególnych elementów pojawiają się pewne nieścisłości. Wpływ na to ma dodany padding: 10px, a także tekst w środku elementów. Po usunięciu tekstu szerokość elementu się zmniejsza, a chyba nie powinno się tak dziać. Czyżbym coś przegapił? Należy pamiętać, że jest to cały czas Working Draft (mimo, że implementacje są już od dawna w Firefox 3 i Safari 3), a więc nad flexible box model cały czas trwają prace i wszystko może się jeszcze zmieniać.

Przykład 3


Przykład 3

#example3 {
display: box;
box-orient: vertical;
box-direction: reverse;
}
#example3 > div {
box-flex: 1;
}

W trzecim przykładzie używamy box-orient: vertical, dzięki któremu elementy ułożone są w pionie (jeden pod drugim), a nowością jest box-direction: reverse, które zmienia kolejność elementów. Teraz pierwszy element w strukturze DOM jest ostatni, wszystkie elementy wyświetlane są teraz w odwrotnej kolejności.

Przykład 4


Przykład 4

#example4 {
display: box;
box-orient: vertical;
}
#example4 > div {
box-flex: 1;
box-ordinal-group: 2;
}
#example4 > div.sticky {
box-ordinal-group: 1;
}

Kolejny przykład przedstawia wykorzystanie box-ordinal-group, dzięki któremu spośród gąszcza losowo dodanych elementów możemy wyłowić ten jeden (lub więcej) istotny, który umieścimy na samej górze listy mimo, że nie musimy nawet wiedzieć gdzie się dokładnie znajduje, wystarczy jakiś odnośnik, np. konkretna klasa sticky. Nawet, jeśli nadal będziemy dodawać kolejne elementy, to ten najważniejszy i tak będzie wyświetlać się na samej górze. Decyduje o tym niższa wartość parametru box-ordinal-group, którym grupujemy elementy i nadajemy im ważność w hierarchii. Nic nie stoi na przeszkodzie, by mieć dwa lub trzy takie elementy, lub tworzyć bardziej skomplikowane konstrukcje składające się z wielu grup.

Przykład 5


Przykład 5

#example5 {
display: box;
box-orient: horizontal;
box-pack: center;
box-align: center;
}

W tym przykładzie zostały użyte dwie nowe właściwości: box-pack: center, który centruje elementy w poziomie, oraz box-align: center, który centruje elementy w pionie. Dzięki temu możemy wyświetlić dowolne elementy na samym środku strony w obu wymiarach bez potrzeby używania margin: 0 auto oraz innych sztuczek.

Podsumowanie

Wszystko to wygląda bardzo ciekawie, jednak pamiętajmy, że prace nadal trwają i właściwości mogą ulegać zmianom. Mimo wszystko widać spore możliwości wykorzystania tych rzeczy w pryszłych projektach.

W sieci, oprócz oficjalnej dokumentacji, znaleźć można kilka bardzo ciekawych wpisów wyjaśniających tą koncepcję, warto się z nimi zapoznać, ponieważ na nich opierałem swój wpis i przykłady.