Jak používat kontejnerová pravidla pro vytváření responzivních komponent

Od počátku bylo základem responzivního webu CSS pravidlo @media. Jejich nevýhoda ale je, že určují použitá pravidla podle velikosti obrazovky zařízení. Díky snaze několika designérů a vývojářů ale můžeme od roku 2022 používat i kontejnerovou podmínku @container, která naopak určuje responzivní styl podle místa dostupného pro konkrétní DOM prvek (tzv. kontejner).

Poznámka: Od května 2021 je níže uvedená funkčnost implementována jako experimentální v nočních buildech Chrome. Očekávám, že do ostrého provozu a ostatních prohlížečů se dostane koncem tohoto roku nebo v průběhu roku 2022.

Containment aneb oddělení kontejneru od stránky

Základem kontejnerových pravidel je již (od ledna 2020) existující CSS vlastnost contain, která dokáže konkrétní DOM prvek převést na kontejner oddělený od zbytku stránky a zajistit jeho nezávislé renderování.

Pro vytvoření responzivní komponenty je nejprve potřeba její wrapper (vnější kontejner) oddělit od zbytku stránky:

.component-wrapper {
    contain: layout size style;
}

Co znamenají jednotlivé hodnoty je popsáno v článku Rychlost zpracování změn CSS.

Kontejnerová pravidla

Poté, co kontejner oddělíte, můžete na něj již začít používat pravidla @container.

Trochu matoucí může být to, že v pravidle neuvádíte odkaz na daný kontejner, ale rovnou pracujete s jeho vnořenými prvky (children). Prohlížeč pak pravidla použije tak, že pro každý prvek najde jeho nadřazený kontejner s vlastností contain. (Tohle je stejný princip jako když prvku nastavíte position: absolute a prohlížeč najde nejbližšího rodiče s vlastností position: relative, aby zjistil, kde má prvek zobrazit.)

Pokud vám vadí, že v CSS není uvedeno jméno kontejneru, můžete vytvořit pravidlo, tak, že uvede jeho jméno do definice selektoru.

//výchozí "mobilní" styl (wrapper uvádím jen pro ujasnění)
.component-wrapper > .component {
    display: flex;
    flex-flow: column;
    //...
}

//styl pro "tablety"
@container (min-width: 768px) {
    .component {
        flex-flow: row;
        //...
    }
}

//styl pro "desktop" (grid)
@container (min-width: 992px) {
    .component {
        display: grid;
        grid-template-rows: 1fr auto 1fr;
        grid-template-columns: 1fr 2fr 1fr;
        //...
    }
}

Výše uvedený styl zobrazí prvky komponenty pod sebou (column flexbox), na tabletu vedle sebe (row flexbox) a na větších obrazovkách (desktop) pak použije grid pro uspořádání prvků podle potřeby.

Ale díky tomu, že místo @media jsme použili @container, nezáleží na skutečném rozlišení zařízení (tedy mobil, tablet, desktop), ale na tom, kde komponentu zobrazíte.

Pokud tedy danou komponentu zobrazíte v těle stránky, kde bude mít 992+px, zobrazí grid, ale když ji na desktopu vložíte do sidebaru, který má jen 400px na šířku, použije komponenta „mobilní“ layout s column flexbox. Pokud ale zobrazíte komponentu v těle stránky na 1376px se 400px sidebarem, zbude na tělo stránky jen ~970px a komponenta použije tabletový layout (row flexbox).

Pozor na to, že klíčem je, že kontejner musí mít nastaveno contain: size, které říká, že prvek musí mít nastavenu pevnou šířku a výšku a tudíž nestačí spoléhat na to, že se kontejner přizpůsobí stránce (např. podle šířky sidebaru). Naopak, pokud chcete komponentu umístit do sidebaru, musíte jí také nastavit požadované rozměry:

.sidebar { 
    width: 400px; 
    padding: 10px; 
}
.sidebar > .component-wrapper {
    width: 380px; //400px - 2 * 10px padding
}

Podpora v prohlížečích

Jak už jsem psal výše, vlastnost contain i podmínka @container jsou nové, takže s velkou podporou nepočítejte. Vlastnost contain je podporována jen ve Firefox a Chrome (+ Opera a Edge) z roku 2020+, takže nepočítejte s IE ani Safari. Podmínka @container zatím není podporovány v žádném oficiálně používaném prohlížeči.

V Chrome můžete podmínku @container zapnout v chrome://flags pod „Enable CSS Container Queries“.

Pro budoucí podporu sledujte https://caniuse.com/css-container-queries.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Tato stránka používá Akismet k omezení spamu. Podívejte se, jak vaše data z komentářů zpracováváme..