☰ menu
Pavel Satrapa

Kontejnerové dotazy

Na stránkách se často vyskytují určité komponenty – unifikované bloky, které se vyskytují na různých místech. Může u nich být žádoucí, aby měnily svou podobu podle okolností.

Typickým příkladem je třeba karta, která obsahuje obrázek, nadpis a popisný text. Je-li dostatek místa, bude uspořádána na šířku a nadpis s textem budou umístěny vedle obrázku. Je-li prostor pro její zobrazení úzký, bude uspořádána svisle, obrázek, nadpis a popisek budou pod sebou.

Responzivní design umožňuje přizpůsobovat vzhled a rozložení prvků na stránce velikosti (typicky šířce) okna prohlížeče. Jenže v tomto případě to nemusí stačit. Ocitne-li se několik karet vedle sebe (například v mřížce), potřebujeme jejich úzkou variantu bez ohledu na to, jak široké je okno prohlížeče.

A tady přicházejí ke slovy kontejnerové dotazy. Jejich základní myšlenka je následující: Prohlásíme určitý prvek na stránce za kontejner a umožníme měnit vlastnosti jeho potomků podle jeho vlastností. V našem příkladu by to znamenalo, že pokud se karta ocitne v úzkém kontejneru, změní své uspořádání na svislé.

Definice kontejneru

K vytvoření kontejneru slouží dvě vlastnosti: container-name mu přidělí jméno a container-type typ. Jméno je nepovinné, typ de facto ano. Kontejnerem pro naše karty bude prvek s třídou obal a zařídíme to následujícími deklaracemi:

.obal {
    container-name: obal;
    container-type: inline-size;
}

Existuje i vlastnost container, která slučuje obě dohromady. Dílčí hodnoty v ní oddělte lomítkem. Ekvivalentní definicí by bylo:

.obal {
    container: obal / inline-size;
}

Pro container-type jsou k dispozici tři hodnoty, ale reálně budete potřebovat jen jednu:

@container

Dostáváme se k podmínkám a pravidlům. Podobně jako @media umožňuje podmínit pravidla určitými vlastnostmi okna prohlížeče, @container funguje podobně pro vlastnosti kontejneru.

Podmínku můžete zahájit jménem kontejneru. V tom případě bude následující podmínky vyhodnocovat jen pro kontejner, kterému jste pomocí container-name přidělili dané jméno. To se hodí, pokud je do sebe vnořeno několik kontejnerů a vy chcete zkoumat jen některý z nich. Bez uvedení jména se budou podmínky vyhodnocovat pro všechny kontejnery odpovídajícího typu, v nichž je prvek obsažen, a pravidla se uplatní, pokud je alespoň jeden splní.

Následují vlastní podmínky. Každá je uzavřena do kulatých závorek a lze z nich vytvářet složitější výrazy pomocí and (musí být splněny obě podmínky), or (alespoň jedna) a not (následující podmínka nesmí být splněna). Změnu uspořádání obsahu karty podle šířky kontejneru, v němž je obsažena, by zajistila následující pravidla:

.obal  {
    container-name: obal;
    container-type: inline-size;
}

.karta {
    display: flex;
    flex-direction: column;
    /* výchozí uspořádání je svislé */
}

@container obal (width >= 30rem) {
/* uplatní se při širokém kontejneru "obal" */
    .karta {
        flex-direction: row;
        /* mění se na vodorovné */
    }
}

Podívejte se na příklad a vyzkoušejte si, jak se mění podoba karet při změně šířky okna prohlížeče.

Pravidla uvnitř kontejnerového dotazu se vztahují jen na potomky kontejneru, jemuž dotaz vyhověl. Pokud by selektory zdejších pravidel vybraly prvky mimo kontejner, neuplatní se na ně. Jestliže například do kontejnerového dotazu vložíte pravidlo:

* {
    color: red;
}

obarví červeně jen potomky kontejneru. Nelze měnit ani kontejner samotný. Docela by se hodilo, kdyby karta mohla být svým vlastním kontejnerem a podle své šířky měnila rozložení. Tak to ale nejde, musí být obsažena v jiném prvku s rolí kontejneru a rozložení mění podle jeho šířky.

Šířka je široko daleko nejpoužívanější podmínkou, ale zdaleka není jedinou. Můžete testovat i jiné rozměry, poměr jeho stran nebo to, zda a v jakém směru lze posouvat jeho obsah. Podívejte se na přehled podmínek.

Stylové kontejnery

Úplně jiný typ podmínek přinášejí stylové kontejnery. Připomenu, že pro ně není třeba definovat container-type, protože jejich typ normal je výchozí hodnotou, takže každý prvek na stránce se chová jako stylový kontejner.

Podmínka má podobu style(), kde uvnitř zapíšete CSS vlastnost a její požadovanou hodnotu. Splní ji ty prvky, ve kterých daná vlastnost má uvedenou hodnotu. Například následující kontejnerový dotaz zapne dělení slov v potomcích prvků, které mají nastaveno zarovnání textu do bloku:

@container style(text-align: justify) {
    * {
        hyphens: auto;
    }
}

Problém spočívá v tom, že stylové kontejnery v této podobě v polovině roku 2025 žádný prohlížeč neimplementuje. Firefox je neumí vůbec a ostatní prohlížeče nabízejí jen velmi omezenou variantu, kdy podmínkou musí být CSS proměnná. Můžete uvést jen její jméno, v tom případě vyhoví jakýkoli prvek, pro který proměnná existuje. Nebo lze uvést jméno i hodnotu, pak vyhoví jen prvky, kde tato proměnná existuje a má zadanou hodnotu.

Například následující úsek CSS nastaví prvkům <article> uvnitř prvku, jehož proměnná --theme má hodnotu dark (nejspíš to bude prvek <body>) světle šedý text na tmavém pozadí:

@container style(--theme: dark) {
    article {
        color: #ddd;
        background-color: #333;
    }
}

Samozřejmě i zde jsou k dispozici operátory and, or a not a podmínky lze komplikovat podle libosti.

Rozměrové jednotky

V pravidlech, která se nacházejí uvnitř kontejnerových dotazů, můžete při zadávání rozměrů používat několik speciálních jednotek:

V mém kontejnerovém příkladu mohou být při úzkém okně kontejnery velmi úzké a nadpis „Loserfenster“ při standardní velikosti 1.5rem přetéká přes pravý okraj. Proto jsem nastavil:

.karta-popis h2 {
    font-size: min(1.5rem, 14cqw);
}

Při širokém kontejneru je menší hodnotu 1.5rem a nadpis bude mít obvyklou velikost. Klesne-li ale šířka kontejneru pod určitou mez, menší hodnotou se stane 14cqw a velikost písma nadpisu se zmenší na 14 % šířky kontejneru, takže se vejde

Další čtení

Podrobný rozbor kontejnerových dotazů najdete na serveru CSS-Tricks nebo na Mozilla Developer Network.