CSS · Урок 12

Продвинутая адаптивность

Одних @media уже мало: современный CSS умеет реагировать на размер контейнера, а не только окна, и сам подбирать значения. Это значит — меньше дублирующих правил и меньше переделок.

clamp(): размер без брейкпоинтов

clamp() принимает три значения: минимальное, предпочтительное и максимальное. Браузер сам решает, сколько применить в зависимости от экрана — шрифт «дышит» на любом устройстве без единого media query.

h1 {
  font-size: clamp(28px, 5vw, 56px);
  /* не меньше 28px, старается быть 5% ширины окна, не больше 56px */
}

.hero {
  padding: clamp(24px, 8vw, 96px);
}
💡
Формула перевода «дизайнерского» размера в процент: желаемая ширина ÷ ширина макета × 100. Для макета 1440px и заголовка 72px получаем ≈ 5vw.

Unit-ы последнего поколения

vh — это 1% высоты окна, но на мобильных браузер «прилипает» и высота меняется. Новые единицы учитывают это:

.fullscreen {
  height: 100dvh; /* спокойно переживает адресную строку браузера */
}

Container queries: дизайн по контейнеру

Карточка может быть маленькой в сайдбаре и большой в сетке. Media query об этом не знает — он смотрит на окно. Container query смотрит на родителя: меняем стили, когда контейнер стал шире.

.switcher {
  container-type: inline-size; /* включить container queries */
}

@container (min-width: 400px) {
  .card { display: flex; gap: 16px; }
}

/* без сторонних правил карточка в узком сайдбаре
   и в широкой сетке ведёт себя по-разному */
⚠️
Для container-type: inline-size у элемента должен быть определён размер — обычно он наследуется от родителя. Сломаться легко, если задать контейнеру ещё и position: absolute без размеров.

Ещё пара трюков

Селектор :has() позволяет стилизовать родителя по условию внутри — например, «карточка, у которой есть кнопка» или «меню, в котором активный пункт».

.section:has(.error) {
  border-color: red;      /* в секции появилась ошибка */
}

.card:has(img) h3 {
  margin-top: 0;          /* у карточки с фото — свой отступ */
}