Martin Michálek Martin Michálek  – 25. 8. 2020

Vlastností contain označujeme části stránky, které jsou izolované od zbytku, proto, aby prohlížeč nemusel překreslovat celou stránku a ušetřil tak výkon.

Prohlížeče se nějakým způsobem snaží nepřepočítávát vzhled celé stránky při každé změně samy. Kromě toho existují kodérské triky jak to udělat v běžném CSS (viz Layout Boundaries). No a poslední možností je použít vlastnost contain.

Celá problematika „CSS Containmentu“ je nejzajímavější ve vlastnosti content-visibility.

Dva příklady

Vlastnost contain může ušetřit výpočetní čas hlavně v případech, kdy náš DOM obsahuje tisíce uzlů. Následující příklady proto berte jako schématické a hodně zjednodušené.

Přidání prvku do DOMu

Tuhle ukázku jsem převzal z dokumentace od Googlu. Máme následující HTML:

<section class="view">
  Home
</section>

<section class="view">
  About
</section>

<section class="view">
  Contact
</section>

A teď JavaScriptem přidáme nový prvek:

<section class="view">
  Home
</section>

<section class="view">
  About
  <div class="newly-added-element">Check me out!</div>
</section>

<section class="view">
  Contact
</section>

Přidání nového prvku spouští rovnou tři kroky procesu překreslování – styly, layout a paint. Blbé ovšem je, že se ten proces spouští pro celý DOM a celou stránku.

Může pak pomoci přidání vlastnosti contain.

Výpis článků mimo viditelnou část obrazovky

Vezměme, že na stránce máme stovky nebo tisíce samostatných položek typu články, produkty nebo třeba tweety. Většinu z nich uživatelé neuvidí v prvním vykresleném viewportu a zároveň jde o samostatné, izolované prvky, které se se zbytkem stránky nijak vzájemně neovlivňují.

Vezměme jejich výpis ve stránce:

<h1>Výpis článků</h1>
<article class="article">
  <!-- … -->
</article>
<article class="article">
  <!-- … -->
</article>

Prvků .article jsou zde alespoň desítky či stovky nebo mají poměrně složitou DOM strukturu uvnitř.

Pomocí vlastnosti contain můžeme prohlížeč informovat, že tyto prvky je možné vyjmout z celkového překreslení stránky:

.element {
  contain: content;
}

Prohlížeči tak dáváme instrukci, že prvky .element, které „nevidí“ ve viewportu může v klidu vynechat z počítání vzhledu celé stránky.

Ušetříme tím v některých situacích slušný renderovací čas.

Typy „containmentu“

Zatím se mi nepovedlo najít vhodné české slovíčko pro teorii, o které se ve specifikaci mluví jako o „CSS containmentu“. Jde o soběstačné a nezávislé zapouzdření prvku, což je ale poněkud kostrbaté označení.

Známe čtyři typy zapouzdření, které jsou zároveň možné hodnoty vlastnosti contain:

  • size
    Zapouzdření pro velikost. Prohlížeči říkám, že velikost prvku nijak neovlivní jeho potomkové. Pokud nastavíme contain:size, je potřeba v CSS také tomuto prvku nastavit nějakou velikost, jinak prohlížeč počítá, že ji má nulovou, což nechceme. Zapouzdření velikosti samo o sobě zase tak moc výkonu při renderování neušetří.
  • layout
    Zapouzdření pro rozvržení. Říkáme tím, že se layout potomků prvku a zbytku stránky nijak vzájemně neovlivňují. Díky tomu může při zápise contain:layout prohlížeč vynechat počítání layoutu vnitřních prvků elementu a zaměřit se jen na prvek, který tuto vlastnost má nastavenou.
  • paint
    Zapouzdření pro vykreslení. Informujeme tímto, že žádný vnitřní prvek nevyčnívá ze svého rodiče. Uvedení contain:paint prohlížeči umožňuje potenciálně přeskočit vykreslení potomků, pokud je prvek mimo obrazovku.
  • style
    Zapouzdření pro styly. Říkáme, že ovlivněný prvek vyjímáme z počítání hodnot napříč dokumentem, které provádějí vlastnosti jako counter-increment, counter-set nebo quotes. contain:style podle všeho nepodporuje Firefox, ale asi to nevadí, protože tato hodnota není zase tak moc užitečná.

Hodnoty vlastnosti contain jde kombinovat, takže můžete například uvést contain: style paint.

Speciální hodnoty

Za účelem zjednodušení problematiky pro nás, autory webů, přichází specifikace se speciálními hodnotami vlastnosti contain:

  • strict
    Všechny typy zapouzdření, kromě stylů. Totéž jako zápis contain: size layout paint.
  • content
    Všechny typy zapouzdření, kromě stylů a velikosti. Totéž jako contain: layout paint.

Hodnota strict ušetří prohlížeče více času, ale zase musíme znát a definovat velikost prvku.

Pojďme se zde vrátit k druhé ukázce – renderování desítek či stovek článků mimo viditelnou část obrazovky:

  • Pokud bychom použili contain:content, nemusíme definovat výšku jednotlivých bloků, ale na druhou stranu ji prohlížeč bude při prvním vykreslení považovat za nulovou a nevykreslí například správně velká rolovátka.
  • Pokud bychom použili contain:strict, prohlížeči musíme výšku sdělit, ale zase nenastane přepočítání velikosti rolovátka.

Podpora: v Safari máme smůlu, ale je nám to jedno

Vlastnost contain nepodporuje Internet Explorer, ani původní MS Edge, což vůbec nevadí.

Ale nevadí nám ani chybějící podpora v Safari. „Containment“ je typickým příkladem postupného vylepšení (progressive enhancement). V Safari prostě nedojde k očekávané úspoře v rychlosti renderování, ale stránka se tam bez problémů vykreslí.

Viz také caniuse.com/css-containment

Odkazy

Používáte vlastnost contain? Napište nám, kde se vám osvědčila a kde naopak ne do komentářů.

Za připomínky autor děkuje Michalovi Matuškovi.

Komentáře

Váš názor? Vaše zkušenosti? Našli jste chybu?