content-visibility: auto + contain-intrinsic-size: ускоряем длинные страницы без виртуализации и CLSЕсли на странице много тяжёлых блоков — карточки, статьи, отзывы, секции лендинга, документация — не всегда нужна виртуализация. Иногда достаточно сказать браузеру: «не рендери то, что далеко за экраном».
Для этого есть:
.content-section {
content-visibility: auto;
contain-intrinsic-block-size: auto 480px;
}Что происходит:
-
content-visibility: auto разрешает браузеру пропускать рендеринг offscreen-блоков;- layout/paint/style откладываются до момента, когда блок приблизится к viewport;
- DOM остаётся на месте: это не виртуализация, элементы не удаляются;
-
contain-intrinsic-block-size задаёт резервный размер, пока реальная высота ещё не посчитана.Главный нюанс — CLS.
Если просто повесить:
.card {
content-visibility: auto;
}браузер может не знать, сколько места должен занимать пропущенный блок. Когда пользователь доскроллит до него, блок отрендерится, получит реальную высоту и может сдвинуть всё ниже.
Поэтому вместе с
content-visibility почти всегда нужен intrinsic size:.article-preview {
content-visibility: auto;
contain-intrinsic-block-size: auto 360px;
}Здесь
360px — fallback-оценка высоты до первого рендера. Ключевое слово
auto позволяет браузеру запомнить реальный размер после рендера и дальше использовать уже его.Практический пример:
<main class="feed">
<article class="feed-card">...</article>
<article class="feed-card feed-card--large">...</article>
<article class="feed-card">...</article>
</main>
.feed-card {
content-visibility: auto;
contain-intrinsic-block-size: auto 320px;
}
.feed-card--large {
contain-intrinsic-block-size: auto 560px;
}Лучше не подбирать один размер для всего. Если блоки сильно отличаются, разбивайте их на классы: обычная карточка, большая карточка, промо-блок, секция с галереей и т.д.
Где это особенно полезно:
- длинные ленты без интерактивной виртуализации;
- страницы документации;
- каталоги с тяжёлыми карточками;
- лендинги с большим количеством секций;
- SSR-страницы, где DOM уже есть, но рендерить всё сразу дорого.
Где быть осторожнее:
- above-the-fold блоки — им это обычно не нужно;
- sticky/anchor-зависимые интерфейсы;
- элементы, размер которых критично влияет на соседей;
- списки на десятки тысяч DOM-узлов — тут виртуализация всё ещё может быть нужна;
- сложные случаи с измерением размеров через JS.
Важно:
content-visibility: auto не уменьшает количество DOM-элементов и не отменяет стоимость JS, обработчиков событий или хранения данных в памяти. Он оптимизирует именно рендеринг: layout, paint и часть работы вокруг них.Хороший паттерн:
@supports (content-visibility: auto) {
.long-page-section {
content-visibility: auto;
contain-intrinsic-block-size: auto 600px;
}
}Так это становится progressive enhancement: браузеры с поддержкой получают ускорение, остальные рендерят страницу как обычно.
Итог: для длинных страниц, где не хочется усложнять архитектуру виртуализацией,
content-visibility: auto — дешёвый способ снизить initial rendering cost. Но без contain-intrinsic-size легко получить layout shifts, поэтому эти свойства почти всегда стоит использовать парой.
