
Привет, Хабр!
Общаясь с коллегами, я заметил, что они незнакомы с последними возможностями CSS. Как обычно, у всех свои причины. У кого-то много повседневной рутины. Кому-то в принципе неинтересно, что нового происходит в CSS. А кто-то по привычке использует подходы десятилетней давности и ему норм.
Как фанату CSS, мне грустно. Сколько же прикольных вещей проходит мимо них. Да и их код может быть меньше, надёжнее и проще для понимания. В общем, я собрал несколько фрагментов кода, которые были популярны давным-давно, и переписал их с помощью новых возможностей CSS.
Давайте посмотрим, что я вам подготовил.
▍ Центрирование элемента с помощью свойства transform
и значения translate(-50%, 50%)
Центрирование элементов всегда было камнем преткновения. Очень долго не было простого способа реализовать эту задачу. Даже на собеседованиях всегда спрашивали: «Как можно отцентрировать элемент со свойством position
и значением absolute
по двум осям?».
Потом появилось свойство transform
, и все массово стали его использовать.
.parent {
position: relative;
}
.parent::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Расскажу, что тут происходит. Сначала происходит смещение элемента с помощью свойств top
и left
. Важно помнить, что браузеры перемещают верхний левый угол. В итоге мы получим, что он будет находиться по центру родительского элемента.
А нам нужно, чтобы в центре была середина элемента. Для этого надо сместить его в противоположную сторону на половину ширины и высоты. Тут и помогает свойство transform
.
Если для него задать значение в процентах, то итоговое значение смещения браузеры будут вычислять относительно свойств width
и height
. В результате мы увидим, как элемент сместится в центр родительского элемента.
Сегодня уже можно сделать проще. Нам больше не надо смещать элементы с помощью свойств top
и left
, а следовательно, и свойства transform
. Значение center
для свойства place-items
сразу сделает всю магию.
.parent {
display: grid;
place-items: center;
}
.parent::before {
content: "";
position: absolute;
}
Также не надо добавлять свойство position
со значением relative
. Поскольку свойств top
и left
больше нет.
▍ Стилизация элементов на основе селекторов +
или ~
Представим, что перед нами поставили задачу реализовать появление подсказки для поля ввода пароля. Когда пользователь ввёл пароль, который удовлетворяет требованиям, она должна будет исчезнуть.
С требованиями жестить не будем. Пусть минимальная длина пароля должна быть минимум четыре символа.
<body>
<!-- встроенная валидация отключена, потому что чаще всего её реализуют самостоятельно -->
<form class="form" novalidate>
<!-- другие элементы -->
<div class="field">
<label class="field__label" for="password">Пароль</label>
<input class="field__input" id="password" type="password" minlength="4" required>
<span class="field__hint">Пароль должен быть больше 3 символов</span>
</div>
<!-- другие элементы -->
</form>
</body>
Исчезновение подсказки будем реализовывать через свойство display
. Будем его добавлять со значением none
к элементу с классом .field__hint
, если пользователь ввёл четыре и более символов.
В разметке нужный элемент находится после поля для ввода, значит, тут надо использовать селектор +
или ~
.
.field__input:valid + .field__hint {
display: none;
}
Только этот способ всегда вызывал проблемы. Кто-то случайно поменял порядок элементов, и код отваливался. Сегодня это можно побороть, заменив этот подход на решение с использованием псевдо-класса :has
.
.field:has(.field__input:valid) .field__hint {
display: none;
}
Теперь наш код фиг сломаешь. Ему всё равно на то, как располагаются элементы в разметке. Больше не будет неожиданных ошибок!
▍ Объявление стека системных шрифтов
В комментариях под статьёй «Как фронтендеру сделать интерфейс дружелюбнее к пользователю. Коллекция HTML/CSS лайфхаков» я нашёл код с использованием ключевого слова system-ui
, когда его поддержкой была неидеальной. Этот комментарий помог мне вспомнить, что раньше был подход использования системных шрифтов.
Суть заключалась в том, что указывались все семейства шрифтов, которые используются в операционных системах по умолчанию. Назвали такой подход «System Font Stack». Было несколько вариантов реализации.
/* реализация Github */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
/* реализация Medium */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue",sans-serif;
}
Сегодня поддержка ключевого слова system-ui
позволяет нам отказаться от этих фрагментов кода. Оно же само говорит браузерам использовать системный шрифт. Больше подсказки не нужны!
Нам осталось просто добавить его в качестве единственного значения для свойства font-family
.
body {
font-family: system-ui;
}
Такой код пишу я. Но если вы хотите, можно добавить вторым значением sans-serif
. Вдруг вам покажется такой код ненадёжным.
▍ Установка размеров с помощью свойств width
и height
для элементов с position: absolute
или position: fixed
Несколько недель назад я проверил, сможет ли ChatGPT заменить меня. Одной из задач было сверстать модальное окно. Далее покажу, какой код написал ChatGPT для его стилизации.
.modal {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
}
Обращу внимание на свойства top
, left
, width
и height
. Браузеры, обработав их, расположат элемент в левом верхнем углу, растянув на всё пространство по ширине и высоте.
Супер решение, которое я лично использовал десять лет. Но его можно сократить до одной строки. Задайте значение 0
для свойства inset
.
.modal {
display: none;
position: fixed;
inset: 0;
z-index: 1000;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
}
Ещё раз скажу, что в первом решении нет проблем. Просто второе короче. Мне кажется, чем меньше кода, тем лучше.
А также вы можете использовать свойство inset
для случаев, когда используется значение absolute
.
.awesome-block {
position: absolute;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
}
▍ Объявление значения для свойств margin
и padding
вместе со значением 0
Проводя код-ревью, я всё ещё замечаю старый подход к объявлению свойств margin
и padding
. Если требуется установить значение только по одной оси, разработчики вынужденно используют значение 0
.
.awesome-block {
margin: 0 auto;
padding: 1rem 0 2rem;
}
Уже не надо так делать. Есть логические CSS-свойства. Они позволяют установить отступ только по оси.
.awesome-block {
margin-inline: auto;
padding-block: 1rem 2rem;
}
Есть стереотип, что логические свойства в этой задаче могут привести к ошибке. Если поменяется направление текста, то вёрстка поедет.
Да, логические свойства зависят от основного направления текста, которое задаётся свойством writing-mode
. Но ошибка может произойти, только если вы будете использовать значения vertical-lr
или vertical-rl
. А это вряд ли случится — если только вы делаете интерфейс для азиатской аудитории, например, японской.
Если же вы поддерживаете японский язык, то уже точно знаете, где могут быть проблемы. И скорее всего, используете логические свойства массово. В других случаях никто не поменяет направление текста так, чтобы были проблемы.
▍ Установка ширины блочного элемента с использованием свойства display
У меня к вам вопрос: «Как можно сделать так, чтобы браузеры рассчитывали ширину блочного элемента по контенту?».
<body>
<div class="awesome-block">
<span>Блочный элемент с текстом</span>
</div>
</body>
.awesome-block {
padding: 0.5rem;
background-color: lightblue;
/* что ещё тут нужно дописать? */
}

Скорее всего, вы вспомните, что можно поменять значение свойства display
на inline-block
, inline-flex
или inline-grid
. И вы будете правы.
.awesome-block {
padding: 0.5rem;
background-color: lightblue;
display: inline-grid;
}
Без вопросов, это проверенный временем способ. Но он не всегда сработает, потому что не всегда можно менять значение свойства display
. Лучше использовать ключевое слово fit-content
.
Я сразу перейду к нашему примеру и добавлю свойство width
со значением fit-content
для элемента с классом .awesome-block
.
.awesome-block {
padding: 0.5rem;
background-color: lightblue;
width: fit-content;
}
А главный плюс нового решения заключается в том, что элементы сохранят своё расположение. Например, в случае с блочными элементами они продолжат располагаться в столбец. В первом решении такого не было бы.
▍ Расположение элементов в столбец с помощью свойства flex-direction
со значением column
Давайте решим простую задачу. Нам нужно расположить несколько элементов друг под другом и задать между ними отступ. А-ля блок с карточками новостей. Сразу скажу, что мы исключаем решение с блочными элементами и свойством margin
для отступов.
Часто я встречаю, что разработчики используют свойство flex-direction
и gap
.
.container {
display: flex;
flex-direction: column;
gap: 1rem;
}
У меня всегда в голове вопрос: «Зачем?». Можно же просто использовать значение grid
для свойства display
.
.container {
display: grid;
gap: 1rem;
}
Это вполне рабочий приём. Так что если вам нужно расположить два элемента в столбец с отступами, то имейте в виду это решение.
▍ Заключение
Вот и всё. Я постарался показать альтернативные подходы и их плюсы. Не знаю, получилось ли хорошо, но в любом случае надеюсь, что вы нашли что-то новое для себя и захотели это использовать в своём коде.
Обязательно напишите, что я упустил, написал не так и в чём не прав. Для этого есть комментарии. А я их читаю.
Спасибо за чтение!
P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
© 2025 ООО «МТ ФИНАНС»
Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (18)
alexzen
17.06.2025 09:24Странные советы. Для центрирования display: flex намного удобнее и читаемость кода выше.
melnik909 Автор
17.06.2025 09:24Ни разу за 10 лет не встречал использование флексов для позиционирования элемента с position: absolute. Надо взять на вооружение!
.parent { display: flex; justify-content: center; align-items: center; } .parent::before { content: ""; position: absolute; }
Вы этот способ имели ввиду?
Spaceoddity
17.06.2025 09:24А зачем тут вообще позиционирование? Как все модалки во всём вебе сейчас выглядят:
.modal-bg{ position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: flex; justify-content: center; align-items: center; background: rgba(0, 0, 0, 0.4); z-index: 1000; } .modal-bg__window{ width: 300px; /* 50% 40vw auto и т.п.*/ }
melnik909 Автор
17.06.2025 09:24Мне показалось, что меня спрашивал не про модалку, а про первый пример. Я попытался пофантазировать, что автор комментария имеет ввиду.
cp_poonam
17.06.2025 09:24Really enjoyed this post! I still come across teams using older CSS methods like translate(-50%, -50%). This article is a great reminder of how far CSS has come. I’ll definitely be referencing this when updating our internal style guides. Appreciate the practical examples!
sfi0zy
17.06.2025 09:24Сегодня уже можно сделать проще. Нам больше не надо смещать элементы с помощью свойств top и left, а следовательно, и свойства transform. Значение center для свойства place-items сразу сделает всю магию.
И заодно создаст побочный эффект в виде изменения логики расположения других элементов в контейнере. Главная фишка приема с transform на 50% взад состоит в том, что этот элемент ни на что не влияет. И двигать можно по мере необходимости, не только на 50%. Это очень удобно при верске "дизайнерской дичи" в рекламе. Вся визуальная фигня вокруг контейнеров с контентом просто существует в своем абсолютно позиционированном мире, и ее не нужно ничем подпирать. А place-items меняет логику для основного контента в контейнерах. Получается лишняя связь между вещами, которые не должны быть связаны. И гибкость решения страдает. Так что новый вариант хорош, но не всегда.
Spaceoddity
17.06.2025 09:24Блин, наверное, пройдусь по всём пунктам попозже. А пока ответ на основной тезис "Общаясь с коллегами, я заметил, что они незнакомы с последними возможностями CSS". Почему сразу незнакомы? Возможно просто стесняются юзать. Как я. Так уж исторически повелось - что у верстальщиков выработалась некоторая инерция в освоении новых фич. И не на пустом месте ;) Потому что перед юзанием каждой подобной фичи, надо сверяться c caniuse, или того хлеще - видеть приписку "*в настройках браузера надо проставить флаг...".
P.S. Одна из немногих фич CSS, за которую я ухватился как только о ней узнал -
display: contents
- как же я её ждал))melnik909 Автор
17.06.2025 09:24Возможно просто стесняются юзать. Как я. Так уж исторически повелось - что у верстальщиков выработалась некоторая инерция в освоении новых фич. И не на пустом месте ;)
Мне кажется дело кроется в том, что вы не доверяете технологиям. Вы же сами об этом пишите. И вы не одиноки. Для многих CSS это черный магический ящик. Это тоже не на пустом месте случилось.
Я пытаюсь, как-то помочь с этим справиться. Могу я немногое. Например, подсказывать куда смотреть. Это я пытаюсь делать
Heggi
17.06.2025 09:24До недавнего времени большинство "революционных" или просто "новых" фич (кавычки тут не зря) тупо не поддерживались большинством браузеров. Фича, которая есть хроме, не факт что есть в каком-нибудь IE или сафари. Особенно сильно с внедрением фич тормозил IE. И лучше использовать старые, проверенные способы и костыли с гарантией работоспособности, нежели идти и проверять новинки во всей куче браузеров.
Сейчас с этим попроще, актуальных браузеров (движков) осталось 3 штуки и теперь главный тормоз на арене - сафари.
Spaceoddity
17.06.2025 09:24Стилизация элементов на основе селекторов
+
или~
Но суть техники о которой вы рассказываете, совсем в другом)) Это уже полноценный siblings. Тут логика переходит уже на совершенно иной уровень.
Ну и как я говорил ранее - настолько крутые фичи пока что откровенно ссыкотно юзать)) Лучше перестраховаться))
Да и потребность в + и ~ не исчезнет (особенно +).
pnmv
когда вижу предложение заменить одно на другое, особенно если последнее менее конкретно, встает главный вопрос - что с производительностью?
melnik909 Автор
Сколь вижу комментариев под статьями о предложениях заменить одно на другое, всегда спрашивают про производительность. Зачем?
Нужно сразу кидать бенчмарки, где все видно. А лучше сразу переходить к прямым оскорблениям
pnmv
я из другой области - пишу вам с делёкого бекенда. извините, если что.
мне правда любопытно, но что-то там пытаться самому городить не хочется. лучше спросить у специалиста.
melnik909 Автор
Уточните, пожалуйста, про какой пример вы говорите?
pnmv
выберите, пожалуйста, наиболее интересный, по вашему мнению, вариант, из числа тех, где "было много, стало мало".
Gary_Ihar
давайте там где :has вместо +, если вы не против?
melnik909 Автор
Хорошо. Попробую из этого сделать статью