Zrozumieć Flexboxa

Wyrównywanie elementów względem osi

W tym rozdziale dowiesz się, jak układać elementy względem poznanych osi, wykorzystując do tego właściwości justify-content, align-content i align-items.

W poprzedniej części poznaliśmy już osie, według których flexbox ustawia elementy znajdujące się w nim. Przypomnijmy, jak wyglądał nasz kod HTML oraz reguły stylowania:

Nauczmy się teraz zarządzać elementami wzdłuż osi main-axis. Służy do tego właściwość justify-content.

Właściwość justify-content

Przyjmuje ona następujące wartości: flex-start, flex-end, center, space-around, space-evenly oraz space-between. Domyślnie justify-content jest ustawione na flex-start - czyli elementy układają się na początku głównej osi, jeden po drugim. Nie musimy ustawiać justify-content na flex-start, chyba że chcielibyśmy nadpisać inny selektor i przywrócić orginalny układ elementów w specyficznym momencie, na przykład w @media.

Ważną rzeczą przy tworzeniu layoutów na flexboxie jest przestrzeń, jaką dysponuje kontener. To znaczy, aby justify-content mogło poprawnie działać, musimy mieć wolne miejsce, w którym nasze elementy mogłyby się układać - gdy mamy szerokie elementy i nie ustawimy flex-wrap na kontenerze, justify-content i inne właściwości pozycjonujące dzieci flexa mogą nie zadziałać.

Zobaczmy więc jaka jest różnica pomiędzy flex-start a flex-end w justify-content:

Jak widzisz, elementy dalej układają się nam w kolejności jaką zapewniło nam flex-direction: row;, jednak w przeciwieństwie do poprzedniego przykładu, są one przyciągnięte do prawej strony kontenera, w którym się znajdują. Działa to podobnie do właściwości float, z tym, że justify-content został stworzony z myślą o projektowaniu layoutów.

Natomiast float służy do umieszczania obrazków w ten sposób, że opływają one np. konkretny paragraf. To, że dało się za jego pomocą tworzyć layouty to raczej efekt uboczny i dlatego też czasami praca z nim bywała problematyczna.

Podobną sytuacje uzyskaliśmy poprzez flex-direction: row-reverse - elementy były przyciągnięte do prawej strony ekranu, ponieważ rysowane są z drugiej strony. Jednak w przypadku row-reverse mamy zmienioną kolejność wyświetlania się kart - byłyby ułożone w kolejności od największej, do najmniejszej. Dzięki justify-content nie wpływamy na kolejność wyświetlania się kart, a jedynie na ich położenie względem main-axis.

Wiemy już, jak ustawić elementy przy krawędziach naszej osi - istnieje też możliwość ułożenia elementów na środku kontenera. Służy do tego justify-content: center.

Jak widzisz, elementy są wypozycjonowane idealnie na środku w osi poziomej, bez żadnego kłopotu - wystarczyła jedna linijka w CSS. Mamy jeszcze do omówienia wartości space-around oraz space-between, jednak zanim do tego dojdziemy, spróbujmy odwrócić nasze osie, tak by elementy układały się w pionie. Pamiętasz jak to zrobić?

Musimy wykorzystać do tego flex-direction, ustawione na column. Dlaczego do tego wracamy? Ponieważ jak już wspomniałem, justify-content pozycjonuje elementy względem main-axis. To znaczy, że nie powinieneś/aś kojarzyć tej właściwości tylko z centrowaniem w poziomie, ponieważ może ona równie dobrze wyrównywać elementy w pionie.

Spójrz na przykład poniżej. main-axis jest teraz osią pionową i justify-content będzie pozycjonował elementy względem niej.

A w przypadku, gdybyśmy ustawili justify-content na flex-end to nasze kolumny zostaną przyciągnięte do dołu kontenera, w ten sposób:

Okej – skoro tą część mamy za sobą, przejdźmy do space-around i space-between. Są to o tyle ciekawe wartości dla justify-content, że osiągnięcie tego samego efektu bez użycia flexboxa byłoby o wiele bardziej problematyczne.

Wróćmy do flex-direction: row i ustawmy justify-content na space-around. Jak sama nazwa wartości wskazuje, flex rozdzieli przestrzeń, którą dany kontener dysponuje, pomiędzy wszystkie elementy, tak, by każdy z nich miał równy odstęp.

Zobaczmy efekt:

Każdy element ma taki sam odstęp z każdej strony. Przy rozszerzaniu okienka (co mam nadzieję robisz) zobaczysz, że w zależności od przestrzeni jaką flex dysponuje, odstępy między poszczególnymi elementami zmieniają się.

Zauważ też, że wizualnie odstępy te nie są równe - dzieje się tak, ponieważ odstęp pomiędzy pierwszym a drugim elementem składa się z dwóch równych marginesów - prawego odstępu pierwszego elementu oraz lewego odstępu drugiego elementu. Czyli odstępy pomiędzy elementami będą wynosiły dwukrotnie więcej, niż odstępy skrajnych elementów od krawędzi kontenera.

Aby były one dokładnie takie same, musielibyśmy wykorzystać właściwość space-evenly.

Super! Przejdźmy dalej i zobaczmy, jak działa wartość space-between na justify-content:

W przypadku space-between, przestrzeń rozłożona jest tylko i wyłącznie pomiędzy poszczególnymi elementami. To znaczy, że elementy "skrajne", które mają tylko jednego sąsiada, nie będą miały odstępu od kontenera, pomijając ich własny margines. W skrócie, nie będzie odstępu od żadnej krawędzi w main-axis

Tak wygląda układanie elementów względem głównej osi. Do pozycjonowania kart w osi przeciwstawnej służą dwie właściwości: align-items i align-content. Zaczniemy od align-items, ale zanim zdefiniujemy go na .card-section zmieńmy niektóre reguły stylowania naszej pojedycznej karty oznaczonej klasą .card.

Na początku tego kursu ustaliliśmy podstawowy wygląd pojedynczego elementu, który miał być ułożony za pomocą flexa - w tym zdefiniowaliśmy wysokość i szerokość. Usuńmy na chwilę właściwości height i width z selektora .card

Zobacz jaki wpływ ma to na nasze elementy. W tym momencie są one tak jakby rozciągnięte w pionie - a mówiąc konkretniej, względem cross-axis. Wynika to z domyślnych wartości na align-items oraz align-content - stretch.

Jeśli zmienimy teraz flex-direction na column, zauważysz, że elementy rozciągają się w poziomie - ponieważ to jest właśnie cross-axis dla elementów układanych kolumnowo. Zobacz, jak to wygląda.

Aby zapobiec efektowi rozciągnięcia, możemy zrobić dwie rzeczy - ustawić na dzieciach, które mają być pozycjonowane przez flexa odpowiednio max-width bądź max-height, w zależności od osi, na której się znajdujemy. Możemy też zmienić wartość align-items.

Właściwość align-items

To jest właśnie powodem dla którego nie widzieliśmy wcześniej tego efektu - mieliśmy zdefiniowaną stałą wysokość i szerokość na selektorze .card. Na razie nie ustawiajmy ich z powrotem - wyłączymy efekt rozciągnięcia przy pomocy właściwości align-items. Przyjmuje ona następujące wartości: flex-start, flex-end, center, stretch oraz baseline.

Pewnie domyślasz się, jak mogą zadziałać flex-start oraz flex-end - ułożą one elementy na początku bądź na końcu osi, której dotyczy align-items, czyli cross-axis.

Jak widzisz, elementy ułożyły się na początku cross-axis, czyli zostały przyciągnięte do lewej. Jeśli ustawisz wartość flex-end, elementy zostaną przyciągnięte do prawej.

Wróćmy jednak do układu wierszowego, ustawijąc flex-directiom: row, a na nim poznamy kolejne właściwości align-items. Najpierw zobaczmy, jak konkretnie zachowuje się flex-end na row. Aby sprawdzić o co chodzi, rozszerz okienko na tyle, aby elementy nie zawijały się do następnych linii.

Jak widzisz, efektów można było się spodziewać. Elementy zostały przyciągnięte do końca cross-axis, czyli do dołu. Jest jednak jedna ważna uwaga, dotycząca align-items.

Właściwość ta układa elementy względem osi przeciwstawnej w danej linii flexa. Co to znaczy?

Jak już wiesz, jeśli mamy ustawioną właściwość flex-wrap na kontenerze umożliwiamy wtedy zawijanie elementów do następnej linii. Nie ustawiamy tutaj odstępów pomiędzy nimi, tylko definiujemy jak mają układać się dzieci w każdej z nich.

Aby zobrazować Ci o co dokładnie chodzi, ustawmy z powrotem wysokość i szerokość naszych kart na odpowiednio 130px oraz 100px. Dodatkowo, na kartach .card-2 .card3 i .card5 nadpiszemy je na height: 150px; oraz width: 90px;.

Jak widzisz, elementy znajdujące się w jednej linii mają teraz różną wysokość i szerokość. Do tego właśnie służy align-items - aby wyrównać elementy w tej samej linii w cross-axis. Za pomocą tej właściwości nie jesteśmy w stanie kontrolować odstępów pomiędzy poszczególnymi liniami.

Aby rozwiać wszelkie wątpliwości, ustawimy align-items na center.

Zauważ, że elementy są teraz wycentrowane tak, że te niższe mają równy odstęp z góry i z dołu. Wartość tego odstępu równa się połowie różnicy wysokości między danym elementem a najwyższą kartą w linii. Jeśli nasz kontener jest na tyle szeroki, że flex-wrap nie musi zawijać elementów do następnego wiersza, wtedy nasze elementy są po prostu wycentrowane w cross-axis.

Tak, jak już powiedzieliśmy, stretch jest domyślną wartością dla align-items i rozciąga elementy w danej linii w osi przeciwstawnej. Pozostało nam w takim razie omówienie wartości baseline.

Wartość ta wyrównuje karty tak, by linia tekstu była równa pomiędzy poszczególnymi elementami w danej linii. Pod uwagę brany jest tutaj pierwszy tekst w danym elemencie, czyli w naszym wypadku numer karty. Najprościej będzie to zaobserować, zmieniając font-size na niektórych selektorach .card-X .plate. Dodatkowo ustawię justify-content na center aby lepiej widzieć tą zależność.

Zauważ, że każda linia flexa (albo jedna, w zależności od rozmiaru Twojego okienka podglądu) jest ułożona tak, by numer każdej karty był ułożony w jednej linijce, tak by wygodnie się go czytało.

Do czego możemy wykorzystać poznane już właściwości? Ustawiając na kontenerze display: flex; oraz justify-content i align-items na center możemy wyrównać dziecko w pionie i w poziomie. Centrowanie elementów w obu osiach jeszcze nigdy nie było tak proste!

Jako dodatkowe ćwiczenie, możesz poeksperymentować z wypozycjonowaniem pojedycznego elementu w każde z wolnych pól. Zachęcam Cię jednak abyś modyfikował każdy przedstawiony przeze mnie przykład - praktyka czyni mistrza.

Pamiętaj, że justify-content wyrównuje elementu względem main-axis a align-content względem cross-axis.

Właściwość align-content

Wiesz już jak wyrównywać elementy w przeciwstawnej osi, ale zauważ, że dalej nie możemy kontrolować odstępów pomiędzy danymi liniami. Nieważne, czy ustawimy flex-end, flex-start, czy center. W tym konkretnym przypadku, elementy zawsze będą miały między sobą tę samą odległość względem cross-axis.

Do zarządzania pozycjonowaniem poszczególnych linii flexboxa służy właściwość align-content - zadziała ona tylko wtedy, kiedy będzie obecna będzie więcej niż jedna linia.

Innymi słowy: align-content odniesie skutek tylko wtedy, kiedy uruchomiony zostanie flex-wrap. Jeśli nasz rodzic nie będzie miał zawijania, czyli domyślnie flex-wrap: nowrap - wtedy nie ma możliwości, aby align-content zadziałał.

Dlatego flex-wrap pomimo tego, że odpowiada tylko za zawijanie wierszy, to jego obecność rzutuje też na cały nasz layout.

Wartością domyślną dla align-content jest stretch, tak jak przy align-items. Wartość ta ma analogiczne działanie do tego, które poznaliśmy przy wyrównywaniu elementów w cross-axis - domyślnie, wszystkie linie mają tę samą wysokość/szerokość oraz zajmują całą dostępną przestrzeń w cross-axis.

Zmieniając wartość na flex-start, wszystkie linie zostaną wyrównane do początku cross-axis, czyli w tym przypadku zostaną przyciągnięte do góry oraz nie będą już rozciągane w pionie.

Wartości, które może przyjąć właściwość align-content są w większości analogiczne do justify-content - możemy nadać jej flex-start, flex-end, space-around, space-between, center oraz stretch - na align-content nie ustawimy jedynie space-evenly.

Ponadto, justify-content nie posiada właściwości stretch. Oprócz tego, jedyna różnica między nimi jest taka, że działają w różnych osiach - justify-content wyrównuje elementy względem main-axis a align-content względem cross-axis.

Ustawienie align-content: flex-end wyrówna linie do końca cross-axis:

Tak jak się spodziewaliśmy! Świetnie, zobaczmy teraz pozostałe wartości. Tak prezentuje się space-around:

Natomiast space-between ustawi nam odstępy pomiędzy elementami, nie pozostawiając wolnej przestrzeni od krawędzi kontenera:

Oraz oczywiście center:

To wszystkie potrzebne właściwości, które ustawiamy na rodzicu, by wypozycjonować elementy znajdujące się wewnątrz niego. W kolejnym rozdziale omówię właściwości które nadajemy na dzieciach flexa, czyli w naszym przykładzie - bezpośrednio na kartach.

Poeksperymentuj z poznanymi właściwościami justify-content, align-content oraz align-items. Jeśli będziesz miał jakieś pytania bądź wątpliwości, śmiało pytaj na koduje: after-hours bądź zostaw komentarz na dole strony.

Koniec rozdziału drugiego