
Привет, Хабр!
Общаясь с фронтендерами, я заметил, что многие не знают новые классные возможности HTML и CSS. Мне от этого грустно. Надо это исправлять!
Я подумал и составил список, состоящий из наиболее рекомендуемых мной новых фишек. Они поддерживаются в большинстве современных браузеров. Решают старые проблемы. Упрощают разработчикам жизнь. В общем суперполезные!
И да, это поверхностный обзор. Я не буду рассказывать все нюансы. Моя цель — проинформировать вас о новых возможностях. Дальше вы уже сами решите, что изучать детальнее.
Больше не буду тянуть. Давайте посмотрим, что я вам подготовил.
Создание всплывающих элементов без использования JavaScript
У всех интерфейсов есть одна часть. Это всплывающие элементы. Поповеры, модалки, менюхи, тултипы и т.д. Некоторые разработчики даже любят делать модалки поверх модалки. Надеюсь, это не вы.
В общем раньше для таких штук нужен был JavaScript. Почти каждый разработчик писал свой jQuery-плагин для них. Хорошо, что больше этого не требуется. HTML полностью позволяет реализовать такие компоненты с помощью Popover API.
Давайте перейду к примеру. Сразу скажу, что я буду использовать примеры из сайта Doka. Так вы сможете визуально посмотреть результат. Для создания всплывающего элемента нам нужно использовать несколько атрибутов.
Сначала мы должны добавить атрибут popover
для элемента, который должен всплыть. Ему же добавим атрибут id
. Он поможет связывать всплывающий элемент с интерактивным элементом, у которого будет объявлен атрибут popovertarget
.
В нашем примере таким элементом будет кнопка.
<body>
<button popovertarget="my-popover">Показать поповер</button>
<div id="my-popover" popover>
<p>Я — простой, но крутой поповер</p>
</div>
</body>
Представляете, больше ничего не надо писать! Все события, доступность и паттерны поведения сразу реализованы. Нам остаётся написать только три атрибута.
Анимация с использованием свойства display больше не проблема
Всплывающий элемент без анимации не может существовать в современных интерфейсах. Только тут всегда была проблема. Браузеры не умели анимировать, если у элемента менялось значение свойства display
с none
на block
(или любую альтернативу).
В качестве примера я сделаю анимацию появления блока с помощью Popover API из предыдущего раздела. Только я сразу хочу извиниться. Я не могу вставить видео или ссылки на демонстрацию.
По этой причине вам придётся довериться мне. Но если хочется перепроверить меня, то можно вставить код в онлайн-песочницы. Теперь к примеру.
<body>
<button popovertarget="my-popover">Показать поповер</button>
<div id="my-popover" class="awesome-block" popover>
<p>Я — простой, но крутой поповер</p>
</div>
</body>
.awesome-block {
width: 150px;
height: 150px;
background-color: lightblue;
transition: opacity 0.7s;
opacity: 0;
display: none;
}
.awesome-block:popover-open {
opacity: 1;
display: block;
}
У нас элемент с классом .awesome-block
будет появляться резко. Это несмотря на то, что мы объявили плавный переход для свойства opacity
.
Починить этот код позволяет правило @starting-style
. Оно даёт нам возможность определить стили, которые браузер применит перед сменой значения свойства display
со значением none
на видимую альтернативу. В нашем примере это значение block
.
.awesome-block {
width: 150px;
height: 150px;
background-color: lightblue;
transition: opacity 0.7s;
opacity: 0;
display: none;
}
.awesome-block:popover-open {
opacity: 1;
display: block;
}
@starting-style {
.awesome-block:popover-open {
opacity: 0;
}
}
В нашем примере мы хотим анимировать свойство opacity
от значения 0
до 1
. Поэтому начальное значение будет 0
. Его мы указали в правиле @starting-style
. Теперь элемент будет плавно появляться.
Но резко исчезать. Правило @starting-style
работает только перед появлением, а с исчезновением оно не дружит. На этот случай у нас теперь есть свойство transition-behavior
.
Его задача простая. Разрешить или запретить плавный переход для свойств, таких как display
. Значение allow-discrete
разрешает. Его мы и добавим в наш пример, а также укажем свойство display
в свойстве transition
.
.awesome-block {
width: 150px;
height: 150px;
background-color: lightblue;
transition: display 0.7s, opacity 0.7s;
transition-behavior: allow-discrete;
opacity: 0;
display: none;
}
.awesome-block:popover-open {
opacity: 1;
display: block;
}
@starting-style {
.awesome-block:popover-open {
opacity: 0;
}
}
Наша анимация работает для появления и исчезновения элемента. Больше не будет никаких хитростей и сложностей. Делайте анимацию спокойно вместе со свойством display
.
Новые возможности организации CSS с помощью слоёв
Представьте, что вы работаете над рефакторингом стилей своего проекта. Проект большой. Над ним трудилось много фронтендеров. Вы встретили правило со сложным селектором.
.use-theme-bg .page .page-title {
color: black;
}
Вам необходимо написать новые стили, переопределив правило. Что будете делать?
Это точно боль. В больших системах нельзя просто так взять и изменить такой селектор. Вы точно поймаете неожиданные баги. А потом ещё будете материть того, кто этот код написал. Обвинять CSS, что он кривой.
Правда он уже позволяет решить эту проблему. Уже несколько лет существуют CSS-слои. Они помогают работать со специфичностью без боли.
Для демонстрации перепишу код так, чтобы новое правило переопределяло правило с селектором .use-theme-bg .page .page-title
.
@layer legacy {
.use-theme-bg .page .page-title {
color: black;
}
}
.page-title {
color: tomato; /* я выиграл */
}
Главная идея заключается в том, что сейчас мы можем разделить CSS на две большие группы: стили со слоями и без. Если мы пишем правила без слоёв, то они имеют больший приоритет над теми, которые находятся внутри них. Именно этот нюанс я использовал в нашем примере.
Также у нас есть возможность использовать множество слоёв и даже указать их приоритетность. Для этого используется правило @layer
, после которого указывается весь список слоёв. Для примера я объявлю слои legacy
, lib
и components
.
@layer legacy, lib, components;
@layer components {
.awesome-block {
color: tomato; /* у меня специфичность селектора 010, но я выиграл */
}
}
@layer legacy {
:is(.awesome-block) {
color: black; /* у меня специфичность селектора 020, но я проиграл */
}
}
@layer lib {
.awesome-block {
color: black; /* у меня специфичность селектора 011, но я проиграл */
}
}
У первого объявленного слоя наименьший приоритет, а у последнего — наибольший. Таким образом, свойство color
из слоя components
более приоритетно, чем такое же свойство из других слоёв и с более специфичным селектором.
Мне так нравится идея слоёв, что я нашёл для вас реальный пример. Есть платформа Subsctak. Вот они используют слои legacy
, tailwind
и pencraft
.

Для более наглядной демонстрации покажу слой tailwind
в инструментах разработчика.

Слои также поддерживают в разных подходах, такие как CSS in JS. Есть библиотеки, которые используют внутри себя слои. В общем вы уже поняли, что я рекомендую вам их попробовать в своих проектах.
Округление значений
При вёрстке интерфейсов иногда получаются значения с десятичной частью. Для примера посмотрите на значение у свойства margin в инструментах разработчика.
У меня есть загон. Меня раздражают значения, содержащие десятичную часть. К сожалению, я довольно часто её вижу, потому что люблю использовать единицы измерения rem
.
html {
font-size: 106.25%; /* здесь будет рассчитано 17px */
}
.awesome-block {
width: 2rem;
height: 2rem;
background-color: tomato;
box-sizing: border-box;
margin: 1.25rem;
}

Пожалуйста, посмотрите внимательно на значение свойства margin
в инструментах разработчика.
Я не буду сейчас подробно обсуждать свои предпочтения. У каждого они свои. Главное, если вас также дробная часть бесит, то теперь у нас есть способ её избежать.
В CSS недавно появилась математическая функция round()
. Как можно догадаться из её названия, она округляет значение. Для неё мы можем использовать способ округления to-zero
. Именно он позволяет отбросить дробную часть.
html {
font-size: 106.25%; /* здесь будет рассчитано 17px */
}
.awesome-block {
width: 2rem;
height: 2rem;
background-color: tomato;
box-sizing: border-box;
margin: round(to-zero, 1.25rem, 1px);
}

Какая же красота! Теперь наши значения будут совсем идеальными.
Более прозрачный синтаксис медиа-запросов
Я познакомился с медиа-запросами в 2012 году. У меня сразу сложилось особое отношение. Мне казалось, что создавать адаптивную верстку было сродни магии.
Только в первое время меня я всегда путался в синтаксисе. Для демонстрации я напишу медиа-запрос с использованием медиа-функции min-width
.
@media (min-width: 1024px) {
body {
background-color: lightblue;
}
}
Я все время забывал, включается ли в диапазон объявленное значение 1024px
. Со временем я всё же запомнил, что да. Но разработчики стандарта помогли мне новым синтаксисом.
Теперь мы можем использовать привычные со школы математические знаки =
, >
и <
. Если мы хотим, чтобы объявленное значение входило в диапазон, то нам нужно использовать сочетание знаков >
и =
.
@media (width >= 1024px) {
body {
background-color: lightblue;
}
}
Если мы не хотим, чтобы значение 1024px
входило в диапазон значений, то можем использовать >
.
@media (width > 1024px) {
body {
background-color: lightblue;
}
}
Я уже точно не запутаюсь. Думаю, и новичкам тоже теперь будет проще. Надеюсь, вы уже захотели внедрить новый синтаксис медиа-запросов, чтобы ваш код был более простым для восприятия.
Заключение
Подведём итог. В этой статье мы рассмотрели:
возможность создавать всплывающие элементы (попапы, тултипы, менюшки) без JavaScript;
анимировать элемент с изменяемым значением
display
с помощью правила@starting-style
и свойстваtransition-behavior
;CSS-слои, предоставляющие возможность перестать страдать от специфичности селекторов;
более прозрачный синтаксис медиа-запросов;
математическую функцию
round()
, которая даёт возможность округлять значения.
Надеюсь, у меня получилось открыть что-то новое для вас, и вы начнёте это изучать. Пожалуйста, поделитесь в комментариях, какая новая фишка HTML и CSS вам понравилась. Не обязательно из этой статьи.
На этом всё. Спасибо за чтение!
P. S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
© 2025 ООО «МТ ФИНАНС»