В мае в актуальных браузерах появились запросы к стилям контейнера и псевдокласс :open. Теперь карточку можно сделать компактной по настройке контейнера, а раскрытый блок — подсветить. Разберём эти приёмы вместе с ошибками формы и всплывающими подсказками.

Основа выпуска — майские новинки Web Features Explorer. Поддержку и хронологию сверили 9 октября 2026 года. Выбрали изменения для карточек, форм и небольших всплывающих интерфейсов.

Сначала — актуальные браузеры. Newly Available означает, что выбранный приём заработал в их последних стабильных версиях, поэтому пример из статьи можно сравнить в каждом из них, прежде чем принимать решение для проекта. До статуса Widely Available проходит 30 месяцев: знакомая возможность получает время распространиться. Оба статуса помогают планировать работу, но поддержку старых браузеров и встроенных браузеров приложений проверяйте по требованиям проекта.

Что получили актуальные браузеры

Запросы к стилям контейнера: плотная карточка в нужном окружении

Карточка урока в основном списке может быть просторной, а в боковой панели — компактной. Container style queries, или запросы к стилям контейнера, задают оформление потомков по значению пользовательского CSS-свойства у контейнера. С 19 мая они Newly Available.

<section class="lesson-block" data-density="compact">
  <article class="lesson-card">
    <h2>Сетка каталога</h2>
    <p>Соберите карточки товаров в адаптивную сетку.</p>
  </article>
</section>
.lesson-block {
  container-name: lessons;
  --density: comfortable;
}

.lesson-block[data-density="compact"] {
  --density: compact;
}

.lesson-card {
  padding: 1.5rem;
  border: 1px solid #bbb;
  border-radius: 0.5rem;
}

@container lessons style(--density: compact) {
  .lesson-card {
    padding: 0.75rem;
    font-size: 0.875rem;
  }
}

Уберите data-density="compact", и карточка вернётся к просторному виду. Окно остаётся прежним. Условие проверяет настройку контейнера, а правило применяет её к карточке внутри него; это полезно для компонента, который переезжает из основного списка в боковую панель, сохраняя одну HTML-разметку.

В этом базовом наборе запросы работают с пользовательскими свойствами, например --density. Нельзя считать, что любой запрос вроде style(display: grid) уже поддерживается во всех браузерах. Сравнение значений тоже требует аккуратности: для незарегистрированного свойства blue и #0000ff не обязательно совпадут.

Запасной вид просторнее. В неподдерживающем браузере остаётся обычная карточка с крупными отступами, поэтому текст и заголовок продолжат занимать место, даже если браузер целиком пропустит условное правило. Если плотность принципиальна для макета, добавьте запасное правило по data-density. Синтаксис и сравнение значений разбирает MDN о запросах к стилям контейнера.

:open: оформите раскрытый details

С 11 мая :open работает в актуальных основных браузерах. Псевдокласс выбирает нативный элемент в открытом состоянии. Для блока с подробностями можно подсветить заголовок, когда читатель его раскрыл.

<details class="help">
  <summary>Как проверить адаптивность?</summary>
  <p>Измените ширину окна и проверьте, что карточки не перекрываются.</p>
</details>
.help > summary {
  padding: 0.75rem;
  cursor: pointer;
}

.help[open] > summary {
  background-color: #eee;
}

@supports selector(:open) {
  .help:open > summary {
    background-color: #e5ddff;
  }
}

Раскрытием управляет <summary>. Запасное правило использует атрибут open; в новом браузере заголовок станет светло-фиолетовым после раскрытия и вернётся к обычному фону, когда пользователь повторно активирует его. Проверьте оба состояния.

У <dialog> тоже есть открытое состояние, а у выпадающего <select> оно связано с открытым выбором. Для поповера, всплывающего элемента с атрибутом popover, нужен отдельный псевдокласс :popover-open. Не заменяйте имена механически: у состояний разная семантика. Детали — в справочнике :open.

ToggleEvent.source: узнайте, какая кнопка открыла поповер

Один справочный поповер можно открыть из разных карточек, сохранив общее содержимое справки и изменив лишь заголовок, по которому человек узнает выбранный урок. Свойство source события переключения сообщает, какой элемент вызвал действие. Оно Newly Available с 11 мая.

<button type="button" popovertarget="lesson-help"
  data-lesson="Сетка каталога">О сетке</button>
<button type="button" popovertarget="lesson-help"
  data-lesson="Проверка формы">О форме</button>

<div id="lesson-help" popover>
  <h2 id="help-title">Учебный материал</h2>
  <p>Откройте задание и проверьте результат в браузере.</p>
</div>
const help = document.querySelector('#lesson-help');
const title = document.querySelector('#help-title');

help.addEventListener('toggle', (event) => {
  if (event.newState !== 'open') return;
  title.textContent = event.source?.dataset.lesson ?? 'Учебный материал';
});

Название приходит от кнопки. Мы записываем его через textContent, поэтому значение воспринимается как текст и не превращается в HTML-разметку, даже если в данных кнопки случайно оказались угловые скобки. Если событие не содержит source или поповер открыли скриптом без источника, останется общий заголовок.

Сам поповер требует поддержки Popover API. Для старого окружения важную справку лучше оставить доступной как обычный текст или отдельную страницу. Событие toggle приходит асинхронно; не ставьте на этот обработчик действие, которое обязано произойти до открытия. У свойства есть описание на MDN.

Что стало широко доступным

:user-invalid и :user-valid: не встречайте человека красным полем

Пустое обязательное поле бывает :invalid сразу после загрузки. Слишком рано. Для формы записи на курс это плохое начало: человек ещё не успел ничего сделать. Мы рекомендуем показывать оформление ошибки по :user-invalid. Вместе с :user-valid он широко доступен со 2 мая.

<form>
  <label for="email">Электронная почта</label>
  <input id="email" name="email" type="email" required
    aria-describedby="email-hint">
  <p id="email-hint">Введите адрес вида name@example.com.</p>
  <button type="submit">Проверить адрес</button>
</form>
#email {
  border: 1px solid #767676;
  padding: 0.5rem;
}

#email:user-invalid {
  border: 2px solid #b00020;
}

#email:user-valid {
  border: 2px solid #18703a;
}

Введите неверный адрес, завершите взаимодействие с полем или попробуйте отправить форму. Момент появления состояния после редактирования может различаться между браузерами. При попытке отправить неверные данные работает нативная проверка ограничений.

Цвет вторичен. Рамка дополняет подпись и подсказку, а сообщение браузера объясняет проблему при отправке. Для собственной системы сообщений понадобится связать текст ошибки с полем и обновлять его состояние. В старом браузере пример сохранит обычную рамку и нативную проверку. CSS не заменяет проверку данных на сервере. Условия срабатывания — в MDN о :user-invalid.

lh: отступ размером со строку

Ориентир — строка. 21 мая единица lh стала широко доступной. Один lh соответствует вычисленной высоте строки текущего элемента. Это удобно, когда вертикальные отступы должны идти в ритме текста.

.description {
  font-size: 1rem;
  line-height: 1.6;
}

.description p {
  margin-block: 0 1.6em;
  margin-block-end: 1lh;
}

Поменяйте высоту строки. Расстояние после абзаца изменится вместе с line-height, поэтому отступ останется равен одной расчётной строке, даже если вы выберете более свободный ритм текста для длинного описания урока. Первая декларация оставлена запасной: браузер без lh получит отступ 1.6em. Фактическая строка с крупной иконкой или изображением может оказаться выше; lh берёт расчётное значение line-height. Сравните lh и rlh, единицу по высоте строки корневого элемента, в справочнике CSS-длин.

Что попробовать в своём проекте

Сначала займитесь формой. Мы рекомендуем заменить раннюю красную рамку на :user-invalid, прежде чем перестраивать систему тем: эту правку можно оценить в одном поле, начав с пустого состояния и дойдя до ошибочной отправки. Затем возьмите карточку, которая встречается в двух окружениях, и проверьте, помогает ли настройка контейнера убрать повторяющиеся правила.

  • Сначала откройте форму с пустыми полями, затем введите неверные данные и попробуйте отправить её.
  • Раскройте <details> клавиатурой.
  • В карточке сравните оба значения --density при одной ширине окна.
  • Откройте поповер обеими кнопками и отдельно проверьте вариант без свойства source; в этом окружении текст заголовка должен оставаться общим и понятным.

Понимает ли человек ошибку формы, если не различает цвет рамки? Осталась ли карточка читаемой в браузере, который игнорирует запрос к стилю контейнера?


«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

ТелеграмПодкастБесплатные учебники