Martin Michálek Martin Michálek  – 21. 8. 2022

Vlastností contain označujeme části stránky, které jsou izolované od zbytku. Izolujeme je proto, aby prohlížeč nemusel při změnách překreslovat celou stránku. Ušetříme tím výkon na stránkách s komplexním DOMem.

Prohlížeče se už dlouho různými způsoby 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 relativně novou možností je použít pro tyhle účely vlastnost contain.

Celá problematika „CSS Containmentu“ je nejzajímavější ve vlastnosti content-visibility, ale silně se využívá také v Container Queries.

Dva příklady

Vlastnost contain může ušetřit čas potřebný pro vykreslování hlavně v případech, kdy 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í – styl, 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.

Podívejme se ještě na jednu ukázku.

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

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

Takhle může vypadat jejich výpis ve stránce:

<h1>Articles</h1>
<article></article>
<article></article>

Představme si, že prvků <article> jsou zde stovky a zároveň mají složitou vnitřní DOM strukturu.

Pomocí vlastnosti contain můžeme prohlížeč informovat, ať tyto prvky vyjme z celkového vykreslování stránky:

article {
  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:

Hodnota contain Typ zapouzdření
size Zapouzdření pro velikost.
Prohlížeči říkám, že velikost prvku nijak neovlivní jeho potomci. Pokud nastavíme contain:size, je potřeba v CSS také tomuto prvku nastavit nějakou velikost. Jinak prohlížeč počítá, že velikost je nulová, což nechceme. Zapouzdření velikosti samo o sobě zase tak moc výkonu při renderování neušetří.
inline-size Zapouzdření pro „inline“ velikost.
Totéž jako size jen pro změny velikosti na vodorovné ose.
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.

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:

Hodnota contain Typ zapouzdření
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či více času, ale zase musíme znát a definovat velikost prvku.

Jak to použít v praxi? 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ů. Na druhou stranu bude prohlížeč při prvním vykreslení považovat výšku 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.

Vlastnost contain vytváří nové kontexty

Pokud containment použijete s hodnotami paint, strict nebo content vytvoří se nové kontexty, které je možné dělat i jinými metodami v CSS:

  • Nový obsahující blok (containing block) – pro potomky, jejichž vlastnost position je absolute nebo fixed, takže něco jako position:relative.
  • Nový kontext stohování (stacking context), ve kterém můžete nezávisle na zbytku stránky umísťovat prvky do vrstev pomocí z-index.
  • Nový kontext formátování bloku (block formatting context), který například umí obsáhnout vnitřní prvky umístěné pomocí float nebo zakáže spojování vnějších okrajů (margin).

Využít containment, konkrétně například contain:content, tedy můžete i v případě, že nechcete šetři výkon, ale usnadnit si kodérskou práci.

Podpora je plná

Vlastnost contain nepodporuje Internet Explorer, což vůbec nevadí. Všechny moderní prohlížeče v containmentu jedou s námi.

Viz také CanIUse.com

Odkazy

Pokud vás problematika containmentu zajímá více, zde je pár tipů k dalšímu studiu:

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