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ávat 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 (hledejte např. „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>
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>
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.
Ilustrační obrázek: Čas potřebný pro fázi layout můžeme snížit díky omezení na konkrétní boxík menšímu počtu prvku k přepočítání. Zdroj developers.google.com.
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.
CodePen: cdpn.io/e/gOrMOWd
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
positionjeabsolutenebofixed, takže něco jakoposition: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í
floatnebo 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/mdn-css_properties_contain
Odkazy
Pokud vás problematika containmentu zajímá více, zde je pár tipů k dalšímu studiu:
- Vlastnost
content-visibility, která z containmentu vychází. - MDN: CSS Containment, vlastnost
contain. - Smashing Magazine: Helping Browsers Optimize With The CSS Contain Property
Za připomínky autor děkuje Michalovi Matuškovi.