
Привет, Хабр. Я продолжаю рассказывать про неизвестные широкому кругу разработчиков CSS фишки. Я отбираю их так, чтобы они были полезны в разного рода проектах. Неважно, верстаете ли вы сайт для малого бизнеса или создаёте супермодное React приложение. Они поддерживаются большинством браузеров. Отдельно отмечу, что я не считаю IE11 современным браузером. По этой причине я не учитывал его.
Сегодня мы рассмотрим:
- как можно избежать длинных значений для свойства
transform
; - можно ли побороть неоднозначность медиа-запросов;
- малоизвестное и полезное свойство при работе с «гридами»;
- какой нюанс вы можете не знать про свойство
align-content
; - древнейшее свойство, помогающее улучшить взаимодействие пользователя клавиатуры с интерфейсом.
Больше не буду затягивать. Давайте посмотрим, что я вам подготовил.
▍ Сегодня можно анимировать трансформацию без длинной цепочки значений
Читатели моих статей периодически просят меня сделать код-ревью их проектов. Проводя его, я заметил один удивительный для меня момент. Многие не знают, что есть отдельные трансформации. Они используют по привычке старое свойство transform
.
В итоге у них получается длинная строка из разных значений трансформации. Чаще всего это происходит при создании сценария анимации, как в коде ниже, где используются значения translate
и rotate
.
.awesome-block::before {
/* Оставшиеся стили */
position: absolute;
top: 50%;
left: 50%;
animation: rotating 1500ms alternate infinite both;
}
@keyframes rotating {
0%, 30% {
transform: translate(-50%, -50%) rotate(0);
}
70%, 100% {
transform: translate(-50%, -50%) rotate(360deg);
}
}
.awesome-block {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid;
position: relative;
}
.awesome-block::before {
content: "";
width: 30px;
height: 30px;
background-color: lightblue;
}
Такое решение долгое время было вынужденным. Если разработчик использовал translate(-50%, -50%)
для центрирования анимированного элемента по горизонтали и по вертикали, то это значение должно использоваться в анимации на каждом шаге. Иначе оно будет переопределено, и элемент будет дёргаться.
Уже давно у нас есть возможность так не делать. Достаточно использовать отдельные свойства трансформации translate
, rotate
и scale
. Например, вот так преобразится наш предыдущий пример.
.awesome-block::before {
/* Оставшиеся стили */
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%; /* тут появилось свойство translate вместо функции translate */
animation: rotating 1500ms alternate infinite both;
}
@keyframes rotating {
0%, 30% {
rotate: 0;
}
70%, 100% {
rotate: 360deg;
}
}
.awesome-block {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid;
position: relative;
}
.awesome-block::before {
content: "";
width: 30px;
height: 30px;
background-color: lightblue;
}
Я заменил значение translate(-50%, -50%)
на свойство translate
и вынес его в основные стили псевдо-элемента .awesome-block::before
. В анимации использую свойство rotate
, которое работает также, как функция rotate()
.
Не надо больше, пожалуйста, писать длинные значения для свойства transform
. Вам же самим потом сложно это всё поддерживать. Делайте ваш код простым.
▍ Уже можно использовать более явный синтаксис медиа-запросов
Мы с вами привыкли к определённому синтаксису медиа-запросов. Пишем @media
, далее медиа-функция min-width
или max-width
, а потом граничное значение. Вот типичный пример.
@media (max-width: 1024px) {
body {
background-color: lightblue;
}
}
Только при таком синтаксисе есть проблема. Я столкнулся с ней во времена, когда обучал вёрстке. Очень много людей забывало, включается ли указанное значение медиа-функции в диапазон. Например, значение 1024px
будет ли включено в диапазоны от 0
до 1024px
?
Конечно, да! Но многие думали, что нет. И не только мои ученики. Эта проблема была масштабной. Хорошо, что появился новый синтаксис медиа-запросов, основанный на математических знаках.
Я сразу перепишу предыдущий пример.
@media (width <= 1024px) {
body {
background-color: lightblue;
}
}
Вот так явно проще понимать! Мы же знаем, что знаки <=
означают меньше или равно. Соответственно, указанное значение будет входить в диапазон.
А можно и этот код упростить. Просто использовать знак <
. Только нужно в этом случае изменить граничное значение с 1024px
на 1025px
.
@media (width < 1025px) {
body {
background-color: lightblue;
}
}
Мне кажется, супер классное нововведение. Только есть ложка дёгтя.
К моему сожалению, есть проблема в популярности синтаксиса. Во всех статьях, которые я видел, используется старый синтаксис. Все курсы, знакомые мне, в своих программах рассказывают только про старый синтаксис. Даже во всех проектах, которые попадались мне на глаза, используется старый синтаксис.
Признаюсь. Я тоже по привычке использовал старый синтаксис. Но я уже исправляюсь! Надеюсь, вы тоже будете использовать новый синтаксис медиа-запросов. Давайте будем делать наш код более явным.
▍ Какое свойство вы забыли использовать при работе с «гридами»
Общаясь с фронтенд-разработчиками о «гридах» (CSS Grids), я часто замечаю, одно заблуждение. Люди думают, что для расположения элементов в столбец или строку обязательно нужно использовать свойства grid-template-columns
или grid-template-rows
. Это не так.
Я сразу перейду к примеру. Давайте посмотрим, что будет после объявления контейнеру с элементами свойства display
со значением grid
.

Элементы выстраиваются друг под другом. Это стандартное поведение, потому что после объявления значения grid
к элементу автоматически применяется ряд свойств. Одним из них является свойство grid-auto-flow
. Оно будет добавлено со значением row
.

По этой причине по умолчанию элементы располагаются в столбец. А ещё мы можем это изменить. Например, указать значение column
, и элементы будут отображены в строку.

Видите, как всё просто? И такой подход абсолютно корректный. Я встречал мнение, что «гриды» надо использовать только для сеток. Это не так. Они подходят для огромного числа задач. Свойство grid-auto-flow
поможет вам.
▍ Что вы не знали про свойство align-content
Свойству align-content
более десяти лет. Казалось бы, уже всё про него известно. Только это не так. Сейчас покажу одну фишечку.
Я буду использовать пример, в котором есть два элемента. Один вложен в другой. Для родительского элемента я добавлю свойство align-content
.
<body>
<div class="awesome-container">
<div class="awesome-block">Великолепный текст</div>
</div>
</body>
.awesome-container {
box-sizing: border-box;
width: 300px;
height: 300px;
border: 2px solid;
align-content: center;
}
.awesome-block {
background-color: lightblue;
}
Раньше я думал, что браузеры просто проигнорируют свойство. А теперь откроем браузер и увидим, что элемент с классом .awesome-block
находится по центру по вертикальной оси.

Да, это не баг. С прошлого года свойство align-content
работает для элемента, у которого установлено свойство display
со значением block
. Просто пишем его, и оно работает.
Это означает, что у нас теперь есть способ выровнять элемент по вертикали с помощью одного свойства. Ура!
▍ Пользователи клавиатуры скажут вам спасибо за использование этого свойства
Продумывая эту статью, я сомневался, стоит ли включать свойство outline-offset
. Оно настолько древнее, что я был уверен, что все про него знают. В общем, отправил я опрос в свой канал. Оказывается, половина моих подписчиков его не знает. Значит, надо рассказывать. Знакомьтесь, свойство outline-offset
.
Чтобы понять смысл свойства, я напомню про свойство outline
. С помощью него мы можем создать обводку вокруг элемента. По умолчанию она будет отображена по границам. Например, я создал обводку прям впритык к свойству border
.
.awesome-link {
display: inline-flex;
padding: 0.75rem 1.25rem;
border: 5px solid;
background-color: pink;
color: #222;
}
.awesome-link:focus-visible {
outline: 4px solid tomato;
}

Свойство outline-offset
может сместить эту обводку. Можно задать положительное и отрицательное значение. В первом случае браузеры будут отдалять обводку от границ элемента. Например, я задам значение 10px
.
.awesome-link {
display: inline-flex;
padding: 0.75rem 1.25rem;
border: 5px solid;
background-color: pink;
color: #222;
}
.awesome-link:focus-visible {
outline: 4px solid tomato;
outline-offset: 10px;
}

При использовании отрицательного значения, обводка будет смещена внутрь на площадь элемента. Так, задавая значение -10px
, я сместил обводку внутрь элемента на расстояние 10 пикселей от границ элемента.
.awesome-link {
display: inline-flex;
padding: 0.75rem 1.25rem;
border: 5px solid;
background-color: pink;
color: #222;
}
.awesome-link:focus-visible {
outline: 4px solid tomato;
outline-offset: -10px;
}

Это вся функция свойства outline-offset
. Да, она очень простая, но, несмотря на свою простоту, очень важная. Здесь мне хочется ответить на вопрос: «А зачем нужно смещать обводку?»
В большинстве случаев я пользуюсь только клавиатурой. Одна из моих проблем — это незаметная обводка вокруг элементов. Хорошо, что крупные проекты хотя бы перестали её убирать. Но мне часто приходится думать: «А где это я сейчас?». Хорошо заметный текущий элемент — очень важная часть моего пользовательского опыта.
Вот такая «мелочь» может упростить мне жизнь. Пожалуйста, учтите это в своих интерфейсах.
▍ Заключение
Давайте подведём итог. В этой статье мы рассмотрели:
- отдельные свойства трансформации
translate
,rotate
иscale
, помогающие избегать длинных значений для свойстваtransform
; - новый синтаксис медиа-запросов;
- упущенное из общего внимания свойство
grid-auto-flow
, позволяющее легко отобразить элементы в столбец или в строку; - свойство
align-content
работает внутри элемента с установленным свойствомdisplay
со значениемblock
; - свойство
outline-offset
, с помощью которого можно улучшить опыт пользователей клавиатуры.
Также, пожалуйста, напишите в комментариях, какие CSS фишки вы используете, о которых другие могут не знать. Буду ждать их. Спасибо за чтение!
P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
P.S.S. Другие статьи из серии можно найти по тегу «sm909_unknown_css».
© 2025 ООО «МТ ФИНАНС»
Telegram-канал со скидками, розыгрышами призов и новостями IT 💻
