Оптимизация рендеринга с помощью content-visibility

Как ускорить рендеринг в один клик: магия content-visibility

Представь ситуацию: ты открываешь тяжеленный лендинг или админку с бесконечным списком карточек. Твой мощный MacBook начинает подозрительно шуметь фанами, а Chrome DevTools показывает честные 15 FPS при скролле. Почему? Потому что браузер — честный малый. Он изо всех сил пытается отрендерить каждый DOM-узел, высчитать каждый отступ и отрисовать каждую тень, даже если этот контент находится где-то в подвале страницы, до которого пользователь доберется (если вообще доберется) через пару минут активного скролла.

Мы тратим кучу времени на оптимизацию JS-бандлов, но часто забываем, что Rendering Pipeline — это то самое узкое горлышко, где умирает производительность. Сегодня я расскажу тебе, как сказать браузеру: «Эй, не трогай это, пока я сам не попрошу», используя всего одно CSS-свойство.

Как мы страдали раньше

Раньше у нас было два пути, и оба — так себе. Либо мы использовали display: none, что полностью вырывало элемент из дерева доступности (привет проблемам с SEO и поиском по странице), либо упарывались по «виртуализации списков» на JavaScript.

Виртуализация — это когда мы руками считаем высоту каждого блока, следим за событием скролла и подсовываем в DOM только те элементы, что видны во вьюпорте. Это сложно, это требует тяжелых либ и часто конфликтует с другими CSS-фишками. Например, когда мы пытались настроить плавную прокрутку через CSS Scroll Snap, виртуализация могла превратить жизнь в ад из-за постоянных пересчетов координат.

Как делать правильно в 2026 году

Теперь у нас есть content-visibility. Это свойство позволяет браузеру пропустить работу по рендерингу (Layout и Painting) для элементов, которые находятся вне экрана. Как только блок попадает во вьюпорт, браузер его отрисовывает. Это нативное решение, которое работает в разы быстрее любого JS-костыля.

Самое крутое значение — auto. Оно дает браузеру полный карт-бланш на оптимизацию. Но есть нюанс: чтобы страница не прыгала при скролле (когда высота блока внезапно меняется с 0 на реальную), нам нужно использовать свойство contain-intrinsic-size. Это своего рода «заглушка», которая говорит браузеру, сколько места зарезервировать под еще не отрендеренный контент.

Иногда разработчики пытаются замаскировать лаги интерфейса, вешая продвинутые CSS-анимации, но если основной поток занят тяжелым Layout-ом невидимых элементов, анимация все равно будет дергаться. content-visibility решает коренную причину проблемы, освобождая ресурсы процессора.

Готовый сниппет кода

Просто добавь этот класс для своих тяжелых секций или элементов списка, и ты увидишь разницу в Interaction to Next Paint (INP) моментально.


/* Применяем магию к тяжелым блокам */
.card-section {
  /* Пропускаем рендеринг, если блока нет на экране */
  content-visibility: auto;
  
  /* Указываем примерную высоту блока, чтобы скроллбар не сходил с ума */
  /* Можно указать одно значение или pair (width height) */
  contain-intrinsic-size: auto 400px;
}

/* Опционально: если мы точно знаем, что контент никогда не должен 
   рендериться прямо сейчас (аналог ленивой загрузки) */
.hidden-offscreen {
  content-visibility: hidden;
}

Частая ошибка новичков

Главный факап, который я вижу на код-ревью — это использование content-visibility: auto без contain-intrinsic-size.

Смотри, что происходит: браузер видит свойство, понимает, что блок вне экрана, и схлопывает его высоту в 0 пикселей. Пользователь начинает скроллить, блок влетает во вьюпорт, браузер его рендерит, высота становится 400px… и БАМ! Весь контент ниже прыгает, а ползунок скроллбара начинает дергаться, как сумасшедший. Это убивает UX и портит показатели Cumulative Layout Shift (CLS).

Запомни: Всегда давай браузеру хотя бы примерную оценку размера контента. Если блоки разной высоты, используй auto 500px — это заставит браузер запомнить последний реальный размер элемента, если он уже был отрендерен.

🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!

🚀 Прокачай свой код

Готовые CSS-сниппеты, разбор продвинутых фишек и эксклюзивные материалы — в нашем Telegram-канале.

Подписаться
error: Content is protected !!
Прокрутить вверх