Современный CSS: полный обзор
Что умеет современный CSS: шестнадцать возможностей с поддержкой, что раньше требовало JavaScript или Sass, плюсы и минусы, четыре примера с проверкой в браузере, ошибки и правила.
Коротко
Современный CSS — это набор возможностей, которые появились в браузерах за последние несколько лет и изменили то, как строятся сайты: container queries, селектор :has(), subgrid, вложенность, каскадные слои, новые функции цвета и плавные размеры. Вместе они убирают большую часть JavaScript, который раньше писали ради раскладки и состояний, и заменяют Sass в повседневной работе. Карточка подстраивается под колонку, в которую её поставили, форма реагирует на ввод без скриптов, карточки в ряд выравниваются сами. Основные возможности уже работают во всех современных браузерах; самые новые добавляют осторожно, с запасным вариантом.
Современный CSS коротко
Главные факты одной таблицей: что имеется в виду, что заменяет и как проверить поддержку.
- Что это
- Возможности CSS, которые за последние годы появились во всех основных браузерах
- Главное
- Container queries, :has(), subgrid, вложенность, @layer, oklch(), clamp()
- Заменяет
- Скрипты раскладки, часть библиотек интерфейса, Sass в повседневной работе
- Сборка
- Не нужна — браузер читает как есть
- Поддержка
- Проверяется по отметке Baseline на MDN и caniuse
- Запасной вариант
@supports— новые возможности только там, где браузер их понимает- Стандарт
- Рабочая группа CSS в W3C; браузеры согласуют приоритеты в ежегодном проекте Interop
Что умеет современный CSS: 16 возможностей
Каждая возможность — с задачей, которую она решает, и поддержкой. «Все современные» — актуальные Chrome, Safari, Firefox и Edge; у самых новых поддержку проверяют перед применением.
| Возможность | Что решает | Поддержка |
|---|---|---|
| Grid | двумерная раскладка страницы или блока | везде |
| subgrid | выравнивание содержимого соседних карточек | все современные |
| @container | компонент подстраивается под место, а не под экран | все современные |
| :has() | стиль элемента по тому, что у него внутри | все современные |
| вложенность | правила внутри правил, как в Sass | все современные |
| @layer | порядок каскада без !important | все современные |
| @property | типизированные переменные, которые можно анимировать | все современные |
| oklch(), color-mix() | ровные цвета и оттенки без препроцессора | все современные |
| clamp() | плавные размеры текста и отступов | везде |
| dvh, svh | настоящая высота экрана на телефонах | все современные |
| text-wrap: balance | ровные строки в заголовках | все современные |
| light-dark() | светлая и тёмная тема одной строкой | все современные |
| @starting-style | анимация появления без скриптов | все современные |
| @scope | стили, ограниченные одной частью страницы | новое — проверять |
| anchor() | подсказки и меню, привязанные к элементу | новое — проверять |
| animation-timeline | анимация, которой управляет прокрутка | новое — проверять |
Что раньше требовало JavaScript или Sass
Десять повседневных задач: как их решали раньше и что делает это теперь.
| Задача | Раньше | Теперь |
|---|---|---|
| Карточка для широкой и узкой колонки | скрипт, который меряет ширину | @container |
| Подсветить поле с ошибкой | скрипт, который добавляет класс | :has(:user-invalid) |
| Части карточек одной высоты | скрипт или фиксированные высоты | subgrid |
| Запретить прокрутку под окном | класс на body из скрипта | html:has(dialog[open]) |
| Вложенные правила и переменные | Sass | вложенность и CSS-переменные |
| Оттенок цвета при наведении | darken() в Sass | color-mix() |
| Размер текста между телефоном и десктопом | несколько медиазапросов | clamp() |
| Первый экран на всю высоту телефона | скрипт, читающий высоту окна | 100dvh |
| Подсказка рядом с кнопкой | библиотека позиционирования | привязка к якорю |
| Плавное появление окна | библиотека анимации | @starting-style |
Плюсы и минусы современного CSS
Современный CSS переносит работу из скриптов в браузер. И выгоды, и издержки идут отсюда.
Плюсы · 6
-
Меньше JavaScript
Раскладка и состояния больше не ждут, пока скрипты загрузятся и выполнятся.
-
Быстрее страницы
Меньше библиотек и никаких сдвигов раскладки от скриптов — это помогает Core Web Vitals.
-
Компоненты сами подстраиваются
Одна карточка работает в основной колонке, в боковой и в окне.
-
Без сборки
Вложенности и переменным больше не нужен препроцессор.
-
Порядок в каскаде
Слои решают конфликты без !important и игр со специфичностью.
-
Лучше доступность
Состояния привязаны к настоящему HTML: нативное окно, проверка формы, фокус.
Минусы · 4
-
Старые браузеры
Устаревшим телефонам и некоторым встроенным браузерам нужен запасной вариант.
-
Неровная поддержка нового
Привязку к якорю и анимации от прокрутки проверяют под каждый проект.
-
Знания устаревают
Многие разработчики всё ещё решают скриптами то, что CSS уже умеет.
-
Тихие отказы
Правило, которое браузер не понимает, пропускается без ошибки.
Как выглядит современный CSS: 4 примера
Четыре задачи, для которых раньше нужны были скрипты. Каждая проверена в настоящем браузере настоящим вводом с клавиатуры.
Container queries
Одна и та же карточка — в две колонки в блоке шириной 640px и в одну в боковой колонке 300px, при любой ширине экрана.
/* Разметка: <section class="cards"> <article class="card"> <img> <div>…</div> </article> </section> */
/* Секция становится контейнером: карточки внутри меряют её ширину */
.cards {
container-type: inline-size;
}
.card {
display: grid;
gap: 1rem;
}
/* Карточка подстраивается под место, куда её поставили, а не под экран:
в широкой колонке картинка слева, в узкой боковой — сверху */
@container (width > 28rem) {
.card {
grid-template-columns: 10rem 1fr;
align-items: start;
}
}
Селектор :has()
Поле краснеет только после того, как человек ввёл значение и ушёл из поля, а не на пустой форме.
/* Поле реагирует на то, что в него ввели, — без JavaScript */
.field:has(input:user-invalid) {
--field-color: oklch(55% 0.2 25);
}
.field label,
.field .hint {
color: var(--field-color, inherit);
}
.field input {
border: 1px solid var(--field-color, #cfd1cf);
}
/* Карточка с картинкой получает две колонки, без картинки — остаётся в одну */
.card:has(> img) {
grid-template-columns: 8rem 1fr;
}
/* Пока открыт диалог, страница под ним не прокручивается */
html:has(dialog[open]) {
overflow: hidden;
}
Subgrid
Три карточки с текстами разной длины: кнопки стоят на одной линии.
/* Карточки в ряд: заголовки, тексты и кнопки выравниваются между карточками,
какой бы длины ни был текст в каждой */
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
gap: 1.5rem;
}
.card {
display: grid;
grid-row: span 3; /* заголовок, текст, кнопка */
grid-template-rows: subgrid; /* строки общие с соседями */
gap: 0.75rem;
}
Слои, токены и вложенность
.hidden из последнего слоя побеждает даже селектор по id из более раннего; текст — 16px при ширине 375px и 20px при 1440px.
/* Порядок слоёв объявляется один раз: более поздний слой побеждает
независимо от веса селектора — !important не нужен */
@layer reset, tokens, components, utilities;
@layer tokens {
:root {
--ink: oklch(21% 0.006 150);
/* плавный размер: 16px на телефоне, 20px на широком экране, без медиазапросов */
--text-base: clamp(1rem, 0.9rem + 0.4vw, 1.25rem);
}
}
@layer components {
.button {
min-height: 2.75rem;
padding-inline: 1.25rem;
border: 0;
font-size: var(--text-base);
background: var(--ink);
color: white;
transition: background-color 0.15s;
/* вложенность без Sass */
&:hover {
background: color-mix(in oklab, var(--ink) 80%, white);
}
&:focus-visible {
outline: 2px solid var(--ink);
outline-offset: 2px;
}
}
}
@layer utilities {
.hidden {
display: none;
}
}
Частые ошибки с современным CSS
-
Запрос без контейнера
Без
container-typeу родителя@containerмолча не срабатывает. -
sizeвместоinline-sizeКонтейнер типа size перестаёт брать высоту от содержимого и схлопывается.
-
100vh на телефонах
Панель браузера закрывает низ первого экрана;
100dvhеё учитывает. -
:invalid вместо :user-invalid
Пустая форма вся красная ещё до того, как человек ввёл хоть букву.
-
Новое без запасного варианта
Там, где браузер возможность не поддерживает, раскладка разваливается, а не упрощается.
-
Слои объявлены по частям
Порядок слоёв задаёт первое упоминание; объявленный в разных файлах, он становится случайным.
7 правил современного CSS в рабочем проекте
-
01
Сверяться с Baseline
Перед применением смотреть отметку на MDN: широко доступно, недавно доступно или ограничено.
-
02
Новое поверх работающего
Базовая раскладка работает везде, а
@supportsдобавляет улучшение там, где его понимают. -
03
Токены в переменных
Цвета, отступы и размеры — CSS-переменные в одном месте.
-
04
Слои в начале
Одна строка
@layer reset, tokens, components, utilitiesв начале главного файла. -
05
Контейнеры для компонентов
Медиазапросы — для страницы, container queries — для того, что живёт внутри неё.
-
06
Логические свойства
padding-inlineиmargin-blockвместо left и right — готовность к любому направлению письма. -
07
Уважать отказ от движения
У каждой анимации есть ветка
prefers-reduced-motion.
Вопросы о современном CSS
Что такое современный CSS?
Возможности последних лет — container queries, :has(), subgrid, вложенность, слои, — которые заменяют скрипты и препроцессоры.
Нужен ли ещё Sass?
Для нового проекта обычно нет: вложенность, переменные и функции цвета есть в самом CSS.
Чем container queries отличаются от медиазапросов?
Медиазапросы смотрят на экран, container queries — на блок, в который поставлен компонент.
:has() медленный?
Нет, при обычном применении; исключение — очень широкие селекторы вроде *:has(…) на огромной странице.
Что со старыми браузерами?
Они получают более простую, но рабочую раскладку; улучшения добавляются через @supports.
Помогает ли современный CSS в SEO?
Косвенно: меньше JavaScript и меньше сдвигов раскладки улучшают Core Web Vitals.
Можно ли анимировать переходы между страницами на CSS?
Да, через View Transitions API — одна строка CSS для переходов между страницами сайта.
Форма
Вёрстка
без лишнего
Верстаю на современном CSS и системе токенов: адаптив без библиотек, состояния без скриптов, быстрые страницы. Расскажите о проекте — отвечу в течение рабочего дня.