Эти CSS-техники устарели
- четверг, 19 июня 2025 г. в 00:00:18

Привет, Хабр!
Общаясь с коллегами, я заметил, что они незнакомы с последними возможностями 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. Присоединяйтесь. Ссылка в профиле.
Telegram-канал со скидками, розыгрышами призов и новостями IT 💻
