contain — CSS Containment

CSS contain — свойство, указывающее браузеру, что элемент и его поддерево изолированы от остального документа в части layout, paint или style, что позволяет браузеру оптимизировать рендеринг, ограничивая scope пересчётов.

Зачем нужно

Без containment изменение одного элемента может вызвать layout/paint для всей страницы. contain говорит браузеру: "внутри этого элемента всё изолировано" — и браузер может пропустить проверку влияния на весь документ. Критично для виджетов, карточек, длинных списков.

Где используется

  • Компоненты в длинных списках (карточки товаров, строки таблицы)
  • Виджеты и independent UI блоки (sidebar, chat, карта)
  • Анимированные элементы
  • content-visibility: auto автоматически добавляет containment

Основной контент

Значения contain

.card {
  contain: layout;   /* layout: изменения внутри не влияют на layout снаружи */
  contain: paint;    /* paint:  содержимое не рисуется за пределами элемента */
  contain: style;    /* style:  счётчики CSS не протекают наружу */
  contain: size;     /* size:   размер элемента не зависит от содержимого */
  contain: content;  /* content = layout + paint (наиболее часто используемое) */
  contain: strict;   /* strict  = layout + paint + size (самое строгое) */
}

Практическое применение

/* Карточки в grid — идеальный кандидат */
.product-card {
  contain: content;
  /* Браузер знает: изменение внутри карточки не влияет на соседей */
  /* Позволяет параллельно обрабатывать несколько карточек */
}

/* Виджет с анимацией */
.animated-widget {
  contain: layout paint;
  /* paint: анимация не создаёт layer для соседних элементов */
}

/* Фиксированного размера блоки */
.avatar {
  width: 48px;
  height: 48px;
  contain: strict;
  /* Браузер может кешировать размер и пропустить relayout */
}

/* Sidebar с независимым контентом */
.sidebar {
  contain: layout;
  /* Изменения в sidebar не вызывают layout в main content */
}

contain vs will-change

/* contain — говорит: "это изолировано от остального" */
.card { contain: layout; }

/* will-change — говорит: "это скоро изменится" */
.card { will-change: transform; }

/* Разные цели:
   contain → оптимизация layout/paint scope
   will-change → создание compositor layer, GPU-ускорение */

Измерение эффекта

// Перед/после contain: измеряем Layout Duration в Performance API
performance.mark('layout-start');

// Динамическое добавление элементов в список
for (let i = 0; i < 100; i++) {
  const card = createCard(data[i]);
  list.appendChild(card);
}

performance.mark('layout-end');
performance.measure('layout', 'layout-start', 'layout-end');
// С contain: layout значительно быстрее

CSS Containment Level 2 — container queries

/* container: создаёт containment context для container queries */
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

@container card (min-width: 300px) {
  .card-image { display: block; }
}

Частые ошибки

  • contain: strict на элементе с неизвестным размером — height: 0 (size containment)
  • contain: paint на элементе с overflow: visible потомками — они обрезаются
  • Применение к inline элементам — containment требует block/inline-block/flex/grid
  • Использование contain вместо content-visibility: auto для off-screen элементов

Связанные темы

Ресурсы