CSS Grid kontra Flexbox

css gird & flexbox

Inspiracja

Po obejrzeniu poniższego wystąpienia Morten Rand-Hendriksen na temat CSS Grid postanowiłam przetestować ten sposób pozycjonowania elementów. Zdecydowanie polecam obejrzenie tej prelekcji.

W tym artykule chciałabym porównać na prostym przykładzie dwie metody: Flexbox oraz CSS Grid.

Wsparcie przeglądarek

Zanim przejdziemy do rzeczy, mała notka na temat wsparcia przeglądarek. Na ten moment (13.08.2017) wsparcie CSS Grid jest częściowe. Istnieją problemy z Internet Explorer, Edge, Opera Mini oraz na starszych wersjach iOS Safari. Z powyższego wideo wynika że już niebawem CSS Grid będzie w pełni wspierany przez Edge, stąd warto się zainteresować tematem CSS Grid.

Wsparcie Flexbox:

flexbox wsparcie przeglądarek
Źródło caniuse.com

Wsparcie CSS Grid:

grid wsparcie przeglądarek
Źródło caniuse.com

 

A jak to wygląda w praktyce i czym się różni CSS Grid od Flexboxa? Przekonajmy się na przykładzie.

Cel

Moim celem jest uzyskanie takiego samego efektu za pomocą dwóch różnych metod. Tutaj jest grafika prezentująca jaki efekt chcę osiągnąć.

css grid i flexbox

Wspólny HTML

Zacznijmy od kodu HTML, który jest wspólny dla obu przykładów. Mamy tutaj div o klasie „container”, który ma czwórkę dzieci, które na potrzeby tego przykładu mają klasy „red”, „blue”, „yellow”, „green”*. W środku każdego dziecka znajduje się paragraf.

*w rzeczywistości starajmy się nadawać nazwy klas opisujące czym dany element jest, a nie jak wygląda

 

<div class="container">
    <div class="red">
        <p>red</p>
    </div>
    <div class="blue">
        <p>blue</p>
    </div>
    <div class="yellow">
        <p>yellow</p>
    </div>
    <div class="green">
        <p>green</p>
    </div>
</div>

Wspólny CSS

W tych przykładach będę używać SCSSa. Na początek dodajemy ogólne style, dla rozróżnienia nadajemy różne kolory poszczególnym dzieciom elementu „container”.

$red: #ed4040;
$yellow: #ffef68;
$blue: #4286f4;
$green: #99e265;

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

.container {
    width: 500px;
    height: 300px;
    margin: 150px auto 0 auto;
    border: 2px solid black;

    .red, .blue, .yellow, .green {
        heigth: 100%;
        width: 100%;
        font-size: 25px;
        text-align: center;
    }
}

.red {
    background-color: $red;
}

.blue {
    background-color: $blue;
}

.yellow {
    background-color: $yellow;
}

.green {
    background-color: $green;
}

Po dodaniu tych stylów otrzymujemy bazę dla obu przykładów.

markup

Flexbox

Krok 1

Na sam początek w CSSie nadajemy elementowi o klasie „container” display: flex. W ten sposób cztery divy, które są bezpośrednimi dziećmi elementu „container” zostały uporządkowane jeden obok drugiego, a nie jak było wcześniej jeden pod drugim.

.container {
    display: flex;
    // tu są jeszcze pozostałe, wspólne style
}

display: flex

Jest to spowodowane zaaplikowanie domyślnej właściwości jaką jest „flex-direction: row”. Stąd elementu układają się jeden koło drugiego w jednym rzędzie (inne właściwości „flex-direction” to  row-reverse, column i column-reverse).

flex-direction: row

Krok 2

Aby uzyskać zamierzony efekt używając flexboxa musimy nieco zmienić strukturę HTML. Zmierzamy do stworzenia trzech divów, które będą w jednym rzędzie, jak na grafice powyżej. Dodajemy div o klasie „column-wrapper”, w którym znajdą się dwa elementy: „blue” i „yellow”. Teraz div o klasie „container” ma trójkę dzieci: „red”, „column-wrapper” oraz „green”.

<div class="container">
    <div class="red">
        <p>red</p>
    </div>
    <div class="column-wrapper">
        <div class="blue">
            <p>blue</p>
        </div>
        <div class="yellow">
            <p>yellow</p>
        </div>
    </div>
    <div class="green">
        <p>green</p>
    </div>
</div>

Po zmianie HTML-a otrzymujemy trzy kolumny.

flexbox

Krok 3

Teraz musimy jeszcze dodać style na elemencie „column-wrapper”. Skorzystamy z właściwości jaką jest „flex”. Dzięki temu będziemy mogli rozdysponować przestrzeń rodzica za pomocą procentowych wartości. Chcemy, żeby div o klasie „column-wrapper” zajmował połowę szerokości swojego rodzica, a pozostałe elementy zajmowały po 25% szerokości.

.column-wrapper {
    flex: 0 1 50%
}

.red {
    background-color: $red;
    flex: 0 1 25%;
}

.green {
    background-color: $green;
    flex: 0 1 25%;
}

Dostajemy następujący efekt:

Krok 4

Stylujemy dzieci elementu „column-wrapper”. Chemy żeby każde dziecko zajmowało połowę wysokości rodzica.

.blue, .yellow {
    height: 50%;
}

Końcowy efekt z użyciem Flexboxa

Tutaj na CodePen zaprezentowany jest ostateczny kod oraz efekt.

See the Pen Flexbox example by SowaProgramuje (@sowaProgramuje) on CodePen.

CSS Grid

Teraz zobaczmy jak uzyskać ten sam efekt, ale z użyciem CSS Grid. Wracamy do naszego podstawowego markupu. Mamy rodzica o klasie „container” oraz czwórkę dzieci: div-y o klasach „red”, „blue”, „yellow” i „green”. W przypadku CSS Grid nie będziemy towrzyć dodatkowych elementów w HTML, jak było w przypadku Flexboxa (div o klasie „column-wrapper”). CSS Grid pozwala na opisanie struktury dokumentu, bez potrzeby dodatkowych div-ów, które mają na celu jedynie wspomóc jego stylowanie.

Krok 1

Podstawowe style już mamy, czas przejść do definiowania CSS Grid. Nadajemy elementowi o klasie „container” display: grid. W efekcie elementy zostały ułożone jeden nad drugim oraz wypełniły całą wysokość rodzica.

.container {
    display: grid;
    // tu są jeszcze pozostałe, wspólne style
}

grid

Firefox udostępnia w swoim inspektorze możliwość podglądu linii CSS Grid-u. Po najechaniu kursorem na kratkę koło display:  # grid pojawiają się linie oddzielające poszczególne „komórki” tzw. „Grid highlighter”.

mozilla grid dev tools

I jeszcze zbliżenie:

Krok 2

CSS Grid można porównać do tabeli. Możemy definiować kolumny oraz wiersze. Tutaj na poniższej grafice demontuję jak musimy podzielić nasz „container”, żeby uzyskać zamierzony efekt. Należy zdefiniować trzy kolumny oraz dwa wiersze. Element „red” będzie zajmować dwie komórki (całą pierwszą kolumnę), element „green”  również będzie zajmować dwie komórki (całą ostatnią kolumnę). W CSS Grid mamy możliwość definiowania położenia elementów w dwóch osiach: pionowej i poziomej.  W przeciwieństwie do Flexboxa, gdzie definiujemy „flex-direction” i jest on tylko jednowymiarowy (row, row-reverse, column lub column-reverse).

css grid example

Trzy kolumny oraz dwa wiersze:

css grid example1

Skoro wiemy ile wierszy i kolumn jest potrzebne czas na zdefiniowanie ich wielkości. CSS Grid wprowadza nową jednostkę jaką jest fr czyli „fraction of available space”. Tutaj można przeczytać więcej na temat jednostek jakie możemy używać z CSS Grid.

css grid example2

Do diva „container” dodajemy następujące style:

.container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr; 
    // to będą trzy kolumny, ich szerokość będzie do siebie w stosunku 1:2:1
    grid-template-rows: 1fr 1fr; 
    // to będą dwa wiersze, ich wysokość będzie do siebie w stosunku 1:1
}

Po dodaniu tego kodu każdy element zajął tylko jedną komórkę w Grid. Zostały dwie puste komórki. Aby to zmienić musimy zdefiniować grid-areas oraz grid-template-area.

grid-template

Krok 3

Grid-area nadawany jest na dzieciach elementu, który ma display grid. Zdefiniowanie nazw konkretnych elementów w CSS Grid pozwoli na prostszą orientację.

.red {
    background-color: $red;
    grid-area: red;
}

.blue {
    background-color: $blue;
    grid-area: blue;
}

.yellow {
    background-color: $yellow;
    grid-area: yellow;
}

.green {
    background-color: $green;
    grid-area: green;
}

Po dodaniu tych stylów wizualnie wygląda to niezbyt dobrze, wręcz jakbyśmy się oddalili od naszego celu, ale jeszcze musimy zdefiniować grid-template-area.

grid area

Krok 4

Czas na zdefiniowanie grid-template-area. Musimy zdefiniować, które elementy będą zajmować które i ile komórek. Będziemy korzystać z grid-area, które zdefiniowaliśmy w poprzednim kroku.

Na elemencie „container” dodajemy

grid-template-areas:
"red blue green"
//w cudzysłowie definiujemy co będzie w poszczególnych komórkach w pierwszym wierszu
"red yellow green"; 
//w drugim cudzysłowie definiujemy kolejny wiersz w naszej "tabeli"

Ostatecznie do elementu „container” zostały dodane takie style:

.container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    grid-template-rows: 1fr 1fr;
    grid-template-areas:
    "red blue green"
    "red yellow green"; 
}

Na poniższej grafice zilustrowane jest definiowanie grid-template-areas.

css grid example

Komórki w których zdefiniowane są takie same grid-areas zostają scalone do jednego obszaru. Element „red” oraz element „green” zajmują po dwie komórki, natomiast element „blue” oraz „yellow” zajmują każdy po jednej komórce.

grid-template-area

Końcowy efekt z użyciem CSS Grid

Tutaj można zobaczyć i przeanalizować samodzielnie ostateczny kod.

See the Pen CSS Grid by SowaProgramuje (@sowaProgramuje) on CodePen.

Podsumowując

CSS Grid jest nowszym sposobem pozycjonowania elementów. Działa on trochę jak tabela, gdzie możemy definiować ilość kolumn, wierszy oraz „scalać” poszczególne komórki. Zarówno CSS Grid jak i Flexbox mają jeszcze wiele innych, bardziej zaawansowanych właściwości, których w tym artykule nie omówiłam, a które są bardzo pomocne w pozycjonowaniu elementów.

Ostatecznie używając CSS Grid kod HTML zajął 2 linie mniej, natomiast SCSS 1 linię mniej.

Dodatkowe materiały

Oto linki do stron, na których można dowiedzieć się więcej na temat CSS Grid:

oraz o Flexbox:

 

Masz jakieś pytania, uwagi do kodu? Daj znać w komentarzu!

19 odpowiedzi do “CSS Grid kontra Flexbox”

  1. Jeśli bawisz się i flex i grid to może pomyśl o jakieś małej serii omawiającej dokładnie oba zagadnienia krok po kroku :)? Wbrew pozorom takich artykułów z konkretnymi przykładami i problemami wcale nie ma dużo, a grid za jakiś czas zrobi się standardem jak flex (a może nie?… w świecie webu nie nie możemy mówić na pewno 🙂

    1. Cześć Tomek, dzięki za komentarz! Postaram się rozwinąć temat. CSS Grid jest całkiem przyjemny, więc chętnie napiszę więcej na ten temat. Sama napotkałam na kilka zagwozdek podczas eksperymentowania z CSS Grid i ciężko mi było znaleźć odpowiedź.

      1. Osobiście odnoszę wrażenie, że flexbox był nie do końca udanym eksperymentem, który jednakowoż pokazał, że da się zrobić w CSS-ie narzędzie do tworzenia layoutów i nie trzeba czekać wieki na pojawienie się sensownego wsparcia. Dlatego też postanowiono stworzyć „lepszy” CSS Grid… który z kolei jest w niektórych miejscach zdrowo przekombinowany.

        A równocześnie obydwa sposoby cierpią na pewne problemy związane z potrzebą spłaszczenia struktury HTML, przez co może ucierpieć semantyka. Co ciekawe, w przypadku CSS Grids rozwiązanie istniało (subgrid), ale nikt nie był nim zainteresowany. Zamiast odpowiedzialnych implementacji znowu wybrano po prostu szybkie…

        1. Czy któryś ze sposobów jest lepszy w kwestii responsywności? Jestem totalnym żółtodziobem, a chciałbym zajać się pisaniem stron. Jakoś flex wydaje mi się bardziej przyswajalny, ale może to kwestia tego że łatwiej mi ułożyć sobie w głowie tworzenie layoutu z jego pomocą.
          Liczę na odpowiedź!

      2. .column-wrapper {
        flex: 0 1 50%
        }

        .red {
        background-color: $red;
        flex: 0 1 25%;
        }

        .green {
        background-color: $green;
        flex: 0 1 25%;

        W jakim celu w tym miejscu stosujemy background-color?
        Pozdrawiam , strona w prosty sposób dobrze tłumaczy 🙂

  2. Bardzo rzeczowo i przystępnie napisane. Zabrakło mi czegoś o object-fit, ale też może nie wszystko na raz. Będę zaglądał częściej. Pozdrawiam serdecznie.

  3. Oglądałem tę prezentację zaraz po tym jak się pojawiła po czym porzuciłem temat na jakiś czas i nie praktykowałem, aż do dzisiaj. Jak CSS Grid ma się teraz tzn. czy jest wykorzystywany? Widać trend, który mógłby wskazywać, że jest to dobre rozwiązanie i czy będzie stosowane? 🙂

    W jaki najpopularniejszy sposób obecnie zapewnia się responsywność w css’ie jeżeli nie w.w. rozwiązaniami?

    1. Zdecydowanie, pracowałam już w dwóch projektach, w których korzystaliśmy z CSS Grid-a i moim zdaniem sprawdza się to rewelacyjnie. A co do najpopularniejszego rozwiązania, to nie wiem nie zgłębiałam się w statystyki, więc nie chcę tu nikogo wprowadzać w błąd.

  4. Hej,
    dzięki za przedstawienie girda i flexboxa na przykładzie! 🙂
    Zauważyłam mały bład w kodzie w klasach:
    .red, .blue, .yellow, .green {
    heigth: 100%;
    width: 100%;
    font-size: 25px;
    text-align: center;
    }
    }
    literówka w „height” plus, jeśli każdy div miałby mieć 100%, to nie zadziała bo będzie wielkości kontenera, myślę że height jest tutaj nie potrzebne.

    Pozdrawiam 🙂

  5. Grid jest potężniejszy od Flexów. Proste rozwiązanie. Potrzebujesz zrobić listę np. aktualności z tytułem, zdjęciami, zajawką treści i w stopce jakaś data aktualności. Chcesz zrobić to na zasadzie kafelków po 3 kolumny. W każdym kaflu masz od góry: tytuł, zdjęcie, zajawka treści, stopka z datą. Flex jak i grid ładnie może do tego posłużyć, ale. W środku mamy dwa elementy o różnych wysokościach (tytuł i zajawka treści). Flexem ciężko Ci będzie uzyskać efekt aby w każdym kaflu zdjęcie było na tej samej wysokości. Gdyby w środku był tylko jeden element o zmiennej wysokości to nie ma problemu. Środek robisz display flex i widok kolumnowy. jeden dynamiczny np tytuł zawsze na górze a zdjęcie ze stopką zawsze do dołu. Ale dwa elementy o zmiennej wysokości już trudno wyrównać we wszystkich kafelkach. Na gridach nie ma tego problemu.

Odpowiedz na „NatkaAnuluj pisanie odpowiedzi

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

This site uses Akismet to reduce spam. Learn how your comment data is processed.