Gratulujeme! Úspěšně jste se přihlásili k odběru novinek Frontend Garden.
Ajaj. Při pokusu o přihlášení k odběru novinek došlo k chybě. Zkuste to prosím znovu.
Frontend Garden
  • Články
  • Slovník nové
  • Instagram
  • GitHub
29. květen 2019 —
  • CSS
— čtení na 9 min.

CSS grid pro mikro layouty

Říká se, že flexbox je nástroj stvořený pro malé layouty. Jeho mladší, zato pokročilejší bratříček CSS grid je zase tolik očekávaným řešením pro velký layout stránky. Co když ale dáme velikost stranou a zaměříme se na to, jaké druhy problémů mohou obě techniky řešit?

Adam Kudrna

Adam Kudrna

Adam je UI developer/designer s více než 20letou zkušeností. Firmám pomáhá stavět design systémy a komponentové UI knihovny a lidem radí, jak je kódovat. O webovém frontendu píše, školí a přednáší. Více o autorovi

CSS grid a flexbox mají hodně společného. Za prvé, nikdy předtím tu nebyl žádný nástroj pro tvorbu layoutu. Kodéři pro ten účel používali techniky určené pro jiné problémy, zejména obtékání obrázků textem (float) nebo bloky v textu (inline-block). Obě nové techniky jsou mnohem mocnější. Umí pružně měnit rozměry obsahu, zarovnávat prvky nebo měnit jejich vizuální pořadí. V řadě situací můžeme použít jeden či druhý nástroj se stejným výsledkem. Pojďme se nejprve v rychlosti podívat, v čem se liší.

1D versus 2D

Podobně tradiční, avšak přesnější než naše úvodní rozlišení gridu a flexboxu říká, že flexbox je pro jednorozměrné layouty, naproti tomu grid pro layouty dvourozměrné. Co to znamená?

Přestože u flexboxu definujeme chování prvku ve dvou směrech (neříkal někdo, že flexbox je jednorozměrný?), nedefinuje to žádný vztah mezi jeho řádky. Flexbox sice umí prvky zalomit do více řádků (nebo sloupců, záleží na směru hlavní osy), ty ale o sobě navzájem nemají žádnou informaci a chovají se zcela nezávisle. Flexbox za sebe poskládá prvky tak, jak mu to vyjde. Zalomení se děje pouze automaticky, ovlivnit ho dokážeme jedině šířkou jednotlivých prvků.

Grid definuje layout pro oba směry v ploše: sloupce i řádky. Prvky pak dokážeme do layoutu přesně umístit a máme plnou kontrolu nad výsledkem, což je něco, co flexbox — v obou směrech zároveň — z principu neumožňuje.

Při rozhodování, který z layoutů použít se podle tohoto rozlišení můžeme řídit pravidlem:

  • Stačí mi kontrola jen nad řádky nebo jen nad sloupci? Použiji flexbox.
  • Potřebuji mít kontrolu nad řádky i sloupci zároveň? Použiji grid.

Content out nebo layout in

Jiný pohled na věc dává otázka, kde chceme layout definovat. V případě flexboxu definujeme většinu vlastností na prvcích, grid zase převážně na kontejneru.

/* Flexbox layout */

.layout {
    display: flex;
    flex-flow: row wrap;
}

.layout__item {
    flex: 1 0 25%;
}

A stejný layout v gridu:

/* Grid layout */

.layout {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: auto;
}

Jak si i později ukážeme, s flexboxem téměř vždy potřebujeme stylovat prvky layoutu, zatímco s gridem nám často postačí definovat jen kontejner. Také je důležité, že nečekaně velký obsah se u gridu stále udrží v layoutu a ostatní prvky překryje, kdežto flexbox další obsah odsune.

Mezera

Další nezanedbatelný detail je způsob, jakým dokážeme určit rozestupy mezi prvky layoutu. Tady flexbox zatím zůstává pozadu. Jediným v principu podobným způsobem, jakým je nyní možné vložit do flexbox layoutu mezery, je totiž symetrické vnější (nebo vnitřní, záleží, co vyhovuje víc) odsazení na všech prvcích. To ale musí být kompenzované záporným vnějším odsazením flex kontejneru.

/**
 * Spacing with flexbox
 *
 * 1. Add spacing between items.
 * 2. Account with the spacing in item width.
 * 3. Compensate the spacing on container so the content
 *    remains aligned with the rest of the page.
 */

.layout {
    display: flex;
    flex-flow: row wrap;
    margin: -0.5rem; /* 3. */
}

.layout__item {
    flex: 1 0 calc(25% - 2 * 0.5rem); /* 2. */
    margin: 0.5rem; /* 1. */
}

Funkční, ale komplikované. Od dnešního CSS můžeme chtít víc.

Grid naproti tomu přichází se speciálními vlastnostmi pro stanovení mezer: grid-column-gap a grid-row-gap, resp. jejich zkratkou grid-gap. To vede k výsledkům přesně dle očekávání, žádná záporná kompenzace není třeba. Ba co víc, výpočty rozměrů jednotlivých prvků layoutu se nám zjednodušší, protože mezeru do nich nebudeme muset započítávat. Právě práce s mezerou bude v našich dalších ukázkách častějším argumentem, než si teď možná myslíme.

/* Spacing with grid layout */

.layout {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: auto;
    grid-gap: 1rem;
}

Jak je vidět, kód je samodokumentující, není třeba nic vysvětlovat v komentářích.

A pozor, v přípravě (v rámci CSS Box Alignment Module Level 3) je následník, nová CSS vlastnost gap. Ta má zobecnit existující grid-gap a bude fungovat pro všechny blokové elementy včetně těch stávajících, tedy např. těch s display: block nebo display: flex, takže od záporné kompenzace odsazení budeme moci časem zcela upustit.

/* Spacing of flexbox layout with gap */
/* Works only in FF 63+ as of May 2019 */

.layout {
    display: flex;
    flex-flow: row wrap;
    gap: 1rem;
}

.layout__item {
    flex: 1 0 auto;
}

Stále však platí, že gap a flexbox budou nejlépe fungovat při automatických šířkách prvků, případně pro šířky v součtu menší než celková šířka kontejneru. Rozdělíme-li celý kontejner beze zbytku jako v příkladech výše, mezeru bude z prvků stále třeba odečíst. Flexbox bohužel nemá k dispozici jednotku fr, která by problém vyřešila.

Nový pohled

Tolik v rychlosti základní rozdíly dvou nejnovějších CSS layoutů, gridu a flexboxu. Když už se v problematice orientujeme, pojďme se podívat na více i méně tradiční návrhové vzory layoutu novýma očima.

Oba přístupy zkusíme porovnat na několika příkladech:

  • media: klasický návrhový vzor pro web
  • row: řádek s prvky vlevo a vpravo
  • notification layout: responzivní layout pro oznámení
  • preview layout: složitější responzivní layout např. pro náhled produktu

Media

Klasický layout užívaný pro komentáře — obrázek vlevo, text vpravo

Snad není příliš odvážné tvrdit, že Media objekt je jeden z neznámějších a nejstarších návrhových vzorů na webu vůbec.

S pomocí flexboxu jej klasicky zapíšeme nějak takto:

/* Media with flexbox */

.media {
    display: flex;
    align-items: flex-start;
}

.media__figure {
    flex: none;
    margin-right: 1rem;
}

.media__body {
    flex: 1;
}

Přestože jde o jednořádkový layout a s mezerou nemáme problém, zápis pomocí CSS gridu je o polovinu kratší a vypadá velice lákavě:

/* Media with grid */

.media {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-column-gap: 1rem;
  align-items: start;
}

Také by vás zprvu nenapadlo grid použít? Pojďme dál.

Row

Jednoduchý layout pro drobná zarovnání k levému a pravému okraji

Opustíme síň slávy návrhových vzorů pro web a vrátíme se k řadovým ukázkám z praxe. Row je úplně jednoduchý layout pro vodorovné rozmístění dvou protilehlých prvků na jednom řádku. Zde se flexbox jeví jako ideální nástroj: jediný řádek, neznámé šířky, automatický rozestup.

/* Row with flexbox */

.row {
    display: flex;
    align-items: baseline;
}

.row__left,
.row__right {
    flex: 0 1 auto;
}

.row__right {
    padding-left: 1rem;
    margin-left: auto;
}

Snad jen pro bezpečnostní mezeru mezi levým a pravým prvkem by se nám hodila nová vlastnost gap.

S gridem gap máme a navíc opět zůstáváme s definicí pouze na kontejneru. Kód znovu zaujme svou přímočarostí a srozumitelností:

/* Row with grid */

.row {
    display: grid;
    grid-template-columns: auto auto;
    grid-column-gap: 1rem;
    justify-content: space-between;
    align-items: baseline;
}

Notification layout

Responzivní layout pro notifikace — ikona, text a výzva k akci

Další z ukázek, Notification layout, je přenositelný responzivní layout pro upozornění a chybové hlášky. S flexboxem by zápis mohl vypadat nějak takto:

/* Notification layout with flexbox */

.notification-layout {
    display: flex;
    flex-flow: row wrap;
    align-items: center;
}

.notification-layout__icon {
  width: 2rem;
  margin-right: 1rem;
}

.notification-layout__message {
  flex: 1;
}

.notification-layout__cta {
  flex: 1 0 100%;
  margin-top: 1rem;
}

@media (min-width: 60em) {
  .notification-layout {
    flex-wrap: nowrap;
  }
  
  .notification-layout__cta {
    flex: 0 1 50%;
    margin-top: 0;
    margin-left: 1rem;
  }
}

Zatím chybějící gap opět nahrazujeme odsazením přes margin, které je třeba anulovat, jakmile je nepotřebujeme.

V grid zápisu využijeme grid-template-areas, abychom zlepšili čitelnost kódu. Zavedení definic jednotlivých prvků layoutu rovnou využijeme pro roztažení oblasti pro CTA (Call To Action) na mobilu přes celou šířku:

/* Notification layout with grid */

.notification-layout {
    display: grid;
    grid-template-columns: 2rem 1fr;
    grid-template-rows: auto auto;
    grid-template-areas:
        "icon message"
        "cta cta";
    grid-gap: 1rem;
    align-items: center;
}

@media (min-width: 60em) {
  .notification-layout {
    grid-template-columns: 2rem 1fr 50%;
    grid-template-rows: auto;
    grid-template-areas: "icon message cta"; 
  }
}

.notification-layout__icon {
    grid-area: icon;
}

.notification-layout__message {
    grid-area: message;
}

.notification-layout__cta {
    grid-area: cta;
}

Můžeme se také spolehnout na autoplacement algoritmus a kód o něco zkrátit:

/* Notification layout with grid and autoplacement */

.notification-layout {
    display: grid;
    grid-template-columns: 2rem 1fr;
    grid-template-rows: auto auto;
    grid-gap: 1rem;
    align-items: center;
}

.notification-layout__cta {
    grid-column: span 2;
}

@media (min-width: 60em) {
    .notification-layout {
        grid-template-columns: 2rem 1fr 50%;
        grid-template-rows: auto;
    }
  
    .notification-layout__cta {
        grid-column: span 1;
    }
}

Preview layout

Responzivní layout např. pro náhled produktu

Preview layout bude naším posledním a nejsložitějším příkladem. Zatímco na mobilech je toto rozvržení čistě lineární, na větších obrazovkách jsou nároky citelně vyšší: prvky rozmístěné přes více sloupců i řádků, navíc změna jejich vizuálního pořadí. Je jasné, že na takto složité přeskládání layoutu flexbox nestačí, aniž bychom si zkomplikovali HTML kód. Život (ani HTML) si komplikovat nechceme, podívejme se proto rovnou na řešení s gridem.

/* Preview layout with grid */

.preview-layout__title,
.preview-layout__description,
.preview-layout__tags {
    margin-bottom: 1rem;
}

@media (min-width: 60em) {
    .preview-layout {
        display: grid;
        grid-template-columns: auto auto 1fr;
        grid-template-rows: auto auto;
        grid-template-areas:
            "title tags cta"
            "description description cta";
        grid-gap: 1rem;
    }
    
    .preview-layout__title,
    .preview-layout__description,
    .preview-layout__tags {
        margin-bottom: 0;
    }

    .preview-layout__title {
        grid-area: title;
        align-self: baseline;
    }

    .preview-layout__description {
        grid-area: description;
    }

    .preview-layout__tags {
        grid-area: tags;
        align-self: baseline;
    }

    .preview-layout__cta {
        grid-area: cta;
        justify-self: end;
        align-self: center;
    }
}

Grid a Internet Explorer

Přestože Internet Explorer byl první prohlížeč, který CSS grid ve verzi 10 implementoval, ty nejhezčí prvky nové syntaxe bohužel nativně nepodporuje. Jedná se zejména o grid-gap, grid-template-areas, align-items a autoplacement.

Není však na místě házet grid do žita. Autoprefixer vzal otěže do vlastních rukou a částečnou podporu těchto nových vlastností pro Internet Explorer zpřístupňuje emulací. Za určitých podmínek je tak možné v zápisu využít velké části moderních vlastností gridu včetně autoplacementu. Dá sa tak říci, že grid dnes podporují všechny významně zastoupené prohlížeče.

Shrnutí

Flexbox a grid jsou velmi mocné nástroje pro tvorbu layoutu webu. Mají hodně společného, každý z nich přitom zvládá i něco, co ten druhý neumí. Jsou situace, kdy můžeme sáhnout po té či oné technice se stejným výsledkem a bez většího rozdílu v zápisu (Notification layout). Jindy grid překvapí v disciplínách, kde bychom čekali jasnou převahu flexboxu (Media, Row). A jsou chvíle, kdy o flexboxu není ani třeba uvažovat nebo kdy je grid alespoň výrazně efektivnější nástroj než jeho starší kolega (Preview layout).

Shrňme si v krátkosti klíčové poznatky:

  • Distribuce a zarovnání jednořádkového obsahu je to, proč byl flexbox navržen. Grid však tyto situace zvládá také a s menší spotřebou kódu.
  • Díky grid-column-gap, grid-row-gap a grid-gap je určování rozestupů mnohem snazší v gridu. Flexbox si musí počkat na novou vlastnost gap. Ani tak ale nedisponuje jednotkou fr, která eliminuje nutnost odečtu mezery z šířky prvku.
  • Udržení stejného layoutu na více řádcích je možné jedině s gridem. Stejně tak kombinace víceřádkových a vícesloupcových prvků.
  • Flexbox má zatím výrazně lepší podporu v prohlížečích. S Autoprefixerem však lze grid bezpečně používat i v produkčním prostředí, a to i s některými moderními vlastnostmi.

Nelze říci, že je jedna z technik lepší než druhá. Grid není flexbox a flexbox není grid. V něčem jsou si podobné, přesto jsou jiné. Obojí je však CSS. Oba přístupy nutí k zamyšlení. Jsou to nástroje, které máme k dispozici a v každém jednotlivém případě se můžeme rozhodnout, který z nich nám vyhovuje víc. A především, nikdo nás nebude honit po poli za to, když se zrovna nerozhodneme dobře.

Související odkazy

  • Use Cases For Flexbox (Rachel Andrew, Smashing Magazine)
  • Best Practices With CSS Grid Layout (Rachel Andrew, Smashing Magazine)
  • Quick! What’s the Difference Between Flexbox and Grid? (Chris Coyier, CSS Tricks)
  • Relationship of grid layout to other layout methods (MDN)
  • Mastering Wrapping of Flex Items (MDN)
  • CSS Grid v Internet Exploreru: Jde to! (Martin Michálek, Vzhůru dolů)

Na pracovní ukázky kódu příkladů z tohoto článku se můžete podívat na CodePen.


Adam Kudrna

Adam Kudrna

Adam je UI developer/designer s více než 20letou zkušeností. Firmám pomáhá stavět design systémy a komponentové UI knihovny a lidem radí, jak je kódovat. O webovém frontendu píše, školí a přednáší. Více o autorovi

Další články od autora:

  • Pozvánka na WebExpo 2025
  • WebExpo 2024 obrazem
  • WebExpo 2023 obrazem
Více k tématu:
  • CSS

Sdílejte

Líbí se vám článek? Podpořte jej sdílením!

X (Twitter) Facebook LinkedIn

Komentujte

Chcete k článku něco doplnit? Našli jste chybu? Napište e-mail.

Adam Kudrna

Nejnovější články

WebExpo — čtení na 3 min.

Pozvánka na WebExpo 2025

Rok se s rokem sešel, přichází měsíc květen a s ním WebExpo 2025, které se po nejistých letech usadilo v tomto jarním termínu. Jaké bude?

  • Adam Kudrna
    Adam Kudrna
Pozvánka na WebExpo 2025
JavaScript — čtení na 10 min.

Jak předcházet chaotické organizaci npm skriptů

Řešíte, jak organizovat skripty napříč projekty přehledně a konzistentně? Inspirujte se systémem, který zjednoduší práci vám i kolegům.

  • Tomáš Litera
    Tomáš Litera
Jak předcházet chaotické organizaci npm skriptů
Reportáž — čtení na 2 min.

FrontKon 2024 obrazem

Frontendisti letos připravili třetí ročník konference FrontKon. Ta se letos historicky poprvé odehrála naživo v Praze, a to v prostorách O2 Universum.

  • Kateřina Klouček Dlouhá
    Kateřina Klouček Dlouhá
FrontKon 2024 obrazem

Odběr novinek

Zadejte svůj e-mail a nenechte si ujít další nové články!

Odesláním formuláře souhlasíte se .
Zpracování osobních údajů probíhá za účelem zasílání newsletteru. Můžete se spolehnout, že vaše osobní údaje nebudeme s nikým sdílet. Z newsletteru se můžete kdykoli odhlásit. Stejně tak můžete kdykoli požádat o úplné smazání svých osobních údajů z naší databáze.
Zkontrolujte svoji e-mailovou schránku a potvrďte své přihlášení kliknutím na odkaz.

Všechna témata

  • Bootstrap
  • CSS
  • Design
  • Dokumentace
  • HTML
  • ITCSS
  • JavaScript
  • Kariéra
  • Kvalita kódu
  • Nástroje
  • No-code
  • Přístupnost
  • PWA
  • Reportáž
  • Rozhovor
  • Rychlost
  • Sass
  • Spolupráce
  • Typografie
  • Variable fonts
  • WebExpo
  • ✏️ Napište článek
  • Autoři
  • Cookies
  • Instagram
  • GitHub

Obsah na tomto webu je publikován pod licencí Creative Commons CC BY-NC 4.0.
Frontend Garden vysázel, zastřihuje a okopává (s ♥️) Adam Kudrna.
Založeno v květnu 2019.