☰ menu
Pavel Satrapa

Mřížka čili grid

S příchodem mřížky jsme dostali do rukou velmi silný nástroj pro rozmístění prvků na stránce. Lze ji využít pro rozvržení celé stránky, nebo jen její dílčí části. Umožňuje umisťovat jednotlivé prvky vedle sebe i nad sebe, vytvářet všelijaké nepravidelnosti a podobně.

Mřížka je koncept známý z typografie. Používá se v bohatě ilustrovaných publikacích, kde se na stránkách míchají obrázky a bloky textu. Základní myšlenkou je, že se příslušná plocha rozdělí do několika sloupců a několika řádků, které vytvoří jakousi osnovu. V rámci ní pak definujete obdélníkové oblasti, do nichž umisťujete jednotlivé prvky.

V typografii je mřížka pravidelná, na webu být nemusí. Jednotlivé její sloupce a řádky mohou mít různé rozměry.

Obalující prvek

Mřížka vznikne, když jejímu obalujícímu prvku přiřadíte v CSS vlastnost display: grid. Děti (tedy přímí potomci) tohoto prvku se tím stanou položkami mřížky a budou do ní umístěny podle vašich instrukcí.

Osnova mřížky může vzniknout automaticky, ale často ji chcete definovat ručně. Slouží k tomu vlastnosti grid-template-columns a grid-template-rows, jimiž určíte počet a rozměry jednotlivých sloupců, respektive řádků. Hodnotu tvoří jejich rozměry oddělované mezerami. Například třísloupcovou mřížku, jejíž první sloupec má šířku 10rem, druhý se automaticky přizpůsobí svému obsahu a třetí zabere 20 % celkové šířky stránky, vytvoříte následovně:

.mrizka {
    display: grid;
    grid-template-columns: 10rem auto 20%;
}

Zajímavou jednotkou je fr, která se roztáhne přes celé zbývající volné místo tak, aby mřížka zabrala veškerý dostupný prostor. Je-li v mřížce více sloupců (řádků) s rozměry ve fr, rozdělí si místo podle jejich počtu. Například při definici:

grid-template-columns: 10rem 3fr 1fr;

bude první sloupec široký 10rem a zbývající místo do maximální celkové šířky si rozdělí druhý a třetí sloupec v poměru 3:1.

Vlastností gap lze nastavit šířku mezery mezi sloupci a/nebo řádky. Hodnotou může být jeden rozměr, který se použijte v obou směrech, nebo rozměry dva. V tom případě první udává velikost vodorovné mezery mezi sloupci a druhý svislé mezery mezi řádky osnovy.

Umisťování prvků

Do mřížky budou umístěny děti prvku, jehož vlastnost display má hodnotu grid. Neřeknete-li jinak, budou umístěny podle svého pořadí ve zdrojovém kódu do jednotlivých polí osnovy po řádcích směrem zleva doprava a shora dolů:

1
2
3
4
5
6
7
8
9

Jejich umístění lze ovládat několika způsoby. Ten základní pracuje s čísly virtuálních linií mezi jednotlivými sloupci (řádky). První se nachází před prvním sloupcem (řádkem) a poslední končí až za posledním. V třísloupcové mřížce tedy najdete linie číslo 1, 2, 3 a 4.

Umístění prvku řídí vlastnosti grid-column a grid-row, kterými určíte, na které sloupcové a/nebo řádkové linii má prvek začínat. Takto umístěné prvky mají přednost. Ostatní, jejichž poloha není stanovena, se automaticky rozmístí do volných polí mřížky. Například v následující mřížce jsem první položce nastavil:

grid-column: 3;
grid-row: 2

a třetí položce jsem nastavil sloupec i řádek 1:

1
2
3
4
5
6
7
8
9

Pozor! Pokud položku umístíte za hranice existující mřížky, dojde k jejímu rozšíření o potřebné sloupce a/nebo řádky (s výchozím rozměrem auto). Například v následující mřížce grid-template-columns definuje stejné tři sloupce jako v předchozích příkladech, ale první položku jsem umístil do 5. sloupce a 2. řádku, takže byly přidány chybějící dva sloupce s automatickou šířkou a byly do nich umístěny dostupné položky:

1
2
3
4
5
6
7
8
9

Položku můžete roztáhnout přes několik řádků a/nebo sloupců. Jediným omezením je, že musí mít vždy obdélníkový tvar. Uděláte to například tak, že do vlastnosti grid-column nebo grid-row přidáte lomítko a za něj číslo linie, na které má prvek skončit. V následující mřížce má první položka nastaveno:

grid-column: 1 / 4;

a druhá:

grid-column: 3;
grid-row: 2 / 6;
1
2
3
4
5
6
7
8
9

Dají se používat i záporná čísla linií, která se počítají od konce. Číslo –1 tedy představuje linii za posledním řádkem či sloupcem. Fungují ale jen pro řádky/sloupce definované pomocí grid-template-columns a grid-template-rows. Automaticky vytvořené se nepočítají. Takže roztažení první položky přes celou šířku mřížky zajistí:

grid-column: 1 / -1;

Ale kdybych se pokusil druhou položku roztáhnout svisle pomocí:

grid-row: 2 / -1;

nedopadne to dobře, protože v definici nemám grid-template-rows, řádky se v mřížce vytvářejí automaticky podle obsahu a hodnota –1 s nimi nepočítá.

Další možností, jak roztáhnout položku, je použít v grid-row nebo grid-column za lomítkem hodnotu span N, kde N je počet řádků/sloupců, které má tato položka zabrat. Takže další možností, jak roztáhnout první buňku přes celou třísloupcovou mřížku, je nastavit jí:

grid-column: 1 / span 3;

Málo používaná je možnost některé linie pojmenovat. Uděláte to tak, že v definici sloupců nebo řádků na příslušné místo vložíte jméno linie uzavřené do hranatých závorek. Například si lze pojmenovat počáteční a koncovou linii pomocí:

grid-template-columns: [zacatek] 1fr 3fr 2fr [konec];

Takto vytvořené identifikátory pak můžete používat místo čísel:

grid-column: zacatek / konec;

Pojmenované oblasti

Osobně s oblibou pro umisťování položek využívám pojmenované oblasti. Vytvoříte je v obalujícím prvku mřížky vlastností grid-template-areas. Její hodnotou jsou mezerami oddělované řetězce, kde každý řetězec odpovídá jednomu řádku. Bývá proto zvykem zapisovat je pod sebe, aby bylo spořádání oblastí na první pohled patrné.

Řetězec řádku pak obsahuje mezerami oddělované identifikátory oblastí, kterými mají být naplněny jednotlivé jeho sloupce. Popis zní složitěji než skutečnost, podívejme se na příklad.

Mějme dvousloupcové rozložení stránky, kde v levém úzkém sloupci bude nejprve menu (jeho oblast pojmenuji menu) a pod ním kalendář akcí (kalendar), vpravo vedle nich bude hlavní obsah stránky (obsah). Nahoře a dole pak bude záhlaví a zápatí přes celou stránku. Definice takové mřížky a jejích oblastí by mohla vypadat následovně:

grid-template-columns: 10rem 1fr;
grid-template-areas:
    "zahlavi  zahlavi"
    "menu     obsah"
    "kalendar obsah"
    "paticka  paticka";
zahlavi
menu
obsah
kalendar
paticka

Umístění prvku pak zajistí vlastnost grid-area, jejíž hodnotou je identifikátor oblasti, do níž má být prvek umístěn. Například pro záhlaví:

header {
    grid-area: zahlavi;
}

Hlavní kouzlo tohoto přístupu spočívá v kombinaci s responzivním designem. Je běžné, že podle šířky okna se mění počet sloupců mřížky a s ním i rozložení položek v ní. Buď musíte pomocí grid-row a grid-column měnit umístění jednotlivých prvků, nebo jednoduše na jednom místě definujete podobu sloupců a pojmenovaných oblastí v nich. Druhá varianta mi připadá výrazně jednodušší a elegantnější. Na prvky v ní nemusíte sahat, jsou stále ve stejně pojmenované oblasti. Jen vždy změníte, kde se daná oblast nachází a jak vypadá.

Posloužím praktickým příkladem: Máme na webu banner (který je široký), kalendář akcí a upoutávky na tři články. Při úzkém okně, například na mobilu, jsou všechny pod sebou:

.mrizka {
    grid-template-columns: 1fr;
    grid-template-areas:
        "banner"
        "kalendar"
        "clanek1"
        "clanek2"
        "clanek3";
}

Pokud se okno rozšíří, přejdeme na dvousloupcové uspořádání, kde nejprve banner zabere oba sloupce a zbývající položky jsou uspořádány po dvojicích:

@media (min-width: 30rem) {
    .mrizka {
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
            "banner   banner"
            "kalendar clanek1"
            "clanek2  clanek3";
    }
}

A bude-li okno ještě širší, nasadíme tři sloupce. Banner bude v prvních dvou, vedle něj kalendář a pod nimi články:

@media (min-width: 60rem) {
    .mrizka {
        grid-template-columns: 1fr 1fr 1fr;
        grid-template-areas:
            "banner   banner   kalendar"
            "clanek1  clanek2  clanek3";
    }
}

Podívejte se na příklad, kde můžete pozorovat chování mřížky při změnách šířky okna.

Oblast pořád musí tvořit souvislý obdélník. Nemůžete udělat něco jako

grid-template-areas: "banner kalendar banner" ...;

Proměnlivý počet sloupců

Je-li obsah tvořen větším počtem menších položek (náhledy fotografií, komentáře, upoutávky na články a podobně), bývá žádoucí měnit počet sloupců mřížky podle šířky okna tak, aby dostupná plocha byla využita co nejúčinněji.

Dá se samozřejmě vytvořit série pravidel @media, kde budete měnit definice sloupců podle šířky okna, ale to je zbytečně složité. V tomto případě, kdy jsou všechny sloupce stejné, lze s výhodou využít funkce repeat(počet, šířka). Následující dvě definice sloupců jsou ekvivalentní:

grid-template-columns: 15rem 15rem 15rem 15rem;
grid-template-columns: repeat(4, 15rem);

Kouzlo spočívá v tom, že počet sloupců nemusíte zadávat explicitně. Lze použít magickou hodnotu auto-fit, která říká „dej tam tolik sloupců dané šířky, kolik se do daného prostoru vejde“. Podívejte se na příklad a zkuste si měnit šířku okna. Sloupce v jeho mřížce jsou definovány pomocí:

grid-template-columns: repeat(auto-fit, 15rem);

Pružnost tohoto přístupu lze posunout ještě o kousek dál, protože ani šířka sloupců nemusí být konstantní. Pro ni lze pro změnu využít funkci minmax(nejmenší, největší), která definuje rozpětí, ve kterém se šířka sloupce může pohybovat. Oblíbenou horní hranicí je hodnota 1fr, díky které se sloupce mohou roztáhnout, aby mřížka zabrala celé dostupné místo. Deklarace:

grid-template-columns: repeat(auto-fit, minmax(15rem,1fr));

znamená „dej do mřížky co nejvíc sloupců širokých alespoň 15rem“. Při změně šířky okna se plynule mění šířky všech sloupců až do okamžiku, kdy je možné přidat jeden další, nebo se naopak musí jeden ubrat. Pak dojde ke skokové změně, jak ilustruje tento příklad.

Podrobný rozbor všech možností mřížky najdete na stránce CSS Grid Layout Guide.