Современный 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, при любой ширине экрана.

card.css
/* Разметка: <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()

Поле краснеет только после того, как человек ввёл значение и ушёл из поля, а не на пустой форме.

states.css
/* Поле реагирует на то, что в него ввели, — без 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.css
/* Карточки в ряд: заголовки, тексты и кнопки выравниваются между карточками,
   какой бы длины ни был текст в каждой */
.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.

base.css
/* Порядок слоёв объявляется один раз: более поздний слой побеждает
   независимо от веса селектора — !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

  1. Запрос без контейнера

    Без container-type у родителя @container молча не срабатывает.

  2. size вместо inline-size

    Контейнер типа size перестаёт брать высоту от содержимого и схлопывается.

  3. 100vh на телефонах

    Панель браузера закрывает низ первого экрана; 100dvh её учитывает.

  4. :invalid вместо :user-invalid

    Пустая форма вся красная ещё до того, как человек ввёл хоть букву.

  5. Новое без запасного варианта

    Там, где браузер возможность не поддерживает, раскладка разваливается, а не упрощается.

  6. Слои объявлены по частям

    Порядок слоёв задаёт первое упоминание; объявленный в разных файлах, он становится случайным.

7 правил современного CSS в рабочем проекте

  1. 01

    Сверяться с Baseline

    Перед применением смотреть отметку на MDN: широко доступно, недавно доступно или ограничено.

  2. 02

    Новое поверх работающего

    Базовая раскладка работает везде, а @supports добавляет улучшение там, где его понимают.

  3. 03

    Токены в переменных

    Цвета, отступы и размеры — CSS-переменные в одном месте.

  4. 04

    Слои в начале

    Одна строка @layer reset, tokens, components, utilities в начале главного файла.

  5. 05

    Контейнеры для компонентов

    Медиазапросы — для страницы, container queries — для того, что живёт внутри неё.

  6. 06

    Логические свойства

    padding-inline и margin-block вместо left и right — готовность к любому направлению письма.

  7. 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 и системе токенов: адаптив без библиотек, состояния без скриптов, быстрые страницы. Расскажите о проекте — отвечу в течение рабочего дня.

Или пишите на [email protected]