Kodokon kodokon.com

Контейнерные запросы и нативная вложенность CSS

Сделай компоненты отзывчивыми к своему контейнеру, а не к вьюпорту, и структурируй таблицы стилей нативной вложенностью.

10 мин · 3 вопросов

Открыть этот урок в Kodokon

Медиазапросы измеряют вьюпорт: карточка, которая показывается и в узкой боковой панели, и в основной сетке, не может корректно подстроиться с их помощью, потому что одна и та же ширина экрана соответствует двум разным контекстам. Контейнерные запросы снимают эту связку: компонент спрашивает про размер своего контейнера. Необходимое условие: явно назначить контейнер через container-type (inline-size, чтобы измерять только горизонтальную ось - самый частый случай), при желании дав ему имя через container-name.

CSS
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

@container sidebar (min-width: 400px) {
  .widget {
    display: grid;
    grid-template-columns: 80px 1fr;
    gap: 12px;
  }
}
Виджет, который подстраивается под свою колонку, а не под экран

Контейнерные единицы дополняют картину: 1cqi равен 1% инлайнового размера запрашиваемого контейнера (есть также cqw, cqh, cqb, cqmin, cqmax). В связке с clamp() они дают плавную типографику для каждого компонента: одна и та же карточка получает заголовок, соразмерный её колонке, где бы она ни оказалась.

CSS
.card-slot {
  container-type: inline-size;
}

.card h2 {
  font-size: clamp(1rem, 5cqi, 1.75rem);
}

@container (max-width: 300px) {
  .card .meta {
    display: none;
  }
}
Единицы cqi и запрос без имени контейнера

Нативная вложенность наконец приносит вложенность без препроцессора. Селектор & ссылается на родительский контекст; медиазапросы и @container вкладываются прямо внутрь правила. Ключевое отличие от Sass: вложенный родитель трактуется так, будто он обёрнут в :is(). Два следствия: специфичность родителя равна специфичности самого сильного из его селекторов, если это список, а & .child не выполняет склейку строк - паттерна Sass &__element для генерации имён BEM нативно не существует.

CSS
.menu {
  display: flex;
  gap: 8px;

  & > li {
    list-style: none;

    &:hover {
      background: #f3f4f6;
    }
  }

  @media (min-width: 768px) {
    gap: 16px;
  }
}
Нативная вложенность: состояния, потомки и медиазапрос

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Почему для переиспользуемой карточки контейнерный запрос предпочтительнее медиазапроса?
    • Движку отрисовки быстрее его вычислять
    • Он реагирует на размер контейнера карточки, который одинаков на любом экране, где колонка узкая
    • Он работает без объявления каких-либо предварительных условий в CSS
    • Он умеет запрашивать высоту вьюпорта в дополнение к ширине
  2. Чему соответствует 5cqi?
    • 5% ширины вьюпорта
    • 5% инлайнового размера запрашиваемого контейнера
    • 5 размеров шрифта контейнера
  3. Чем нативная вложенность отличается от вложенности в Sass?
    • Нативная вложенность запрещает вкладывать медиазапросы внутрь правила
    • Нативная вложенность трактует родителя как обёрнутого в :is() и не допускает склейку вида &__element
    • Нативной вложенности нужен препроцессор, чтобы скомпилировать символ &
    • Нативная вложенность ограничивает вложенность одним уровнем