Продвинутая адаптивность
Одних @media уже мало: современный CSS умеет реагировать на размер контейнера, а не только окна, и сам подбирать значения. Это значит — меньше дублирующих правил и меньше переделок.
clamp(): размер без брейкпоинтов
clamp() принимает три значения: минимальное, предпочтительное и максимальное. Браузер сам решает, сколько применить в зависимости от экрана — шрифт «дышит» на любом устройстве без единого media query.
h1 {
font-size: clamp(28px, 5vw, 56px);
/* не меньше 28px, старается быть 5% ширины окна, не больше 56px */
}
.hero {
padding: clamp(24px, 8vw, 96px);
}
5vw.Unit-ы последнего поколения
vh — это 1% высоты окна, но на мобильных браузер «прилипает» и высота меняется. Новые единицы учитывают это:
100dvh— динамическая высота окна;svh— наименьшая,lvh— наибольшая.cqi/cqw— 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; /* у карточки с фото — свой отступ */
}