
Привет, Хабр!
В последние годы CSS стабильно развивается. По себе знаю, что уследить непросто. По этой причине многие продолжают использовать лишь часть его возможностей, ограничиваясь проверенными годами решениями.
Ничего против них не имею. Просто хочу рассказать о нескольких приёмах, которые вы могли упустить. Они помогут вам в разных ситуациях.
Давайте посмотрим, что я вам подготовил.
Надёжный способ задать позицию дочернего элемента «до последней колонки» внутри CSS-гридов
Давайте представим, что мы сверстали сетку с использованием CSS-гридов. Нам нужно сделать так, чтобы дочерний элемент занимал всё пространство, начиная со второй колонки до самого конца.
Лично я для этой задачи обычно использую свойство grid-column с ключевым словом span.
<body>
<div class="awesome-container">
<span class="awesome-block">Здесь волшебный текст</span>
</div>
</body>
.awesome-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
box-sizing: border-box;
min-height: 50dvh;
border: 4px solid purple;
}
.awesome-block {
grid-column: 2 / span 2;
background-color: pink;
}

Я выбрал такой способ, потому что он суперочевидный. Указал позицию и сколько колонок элемент занимает — и всё. Супер же.
Но я не задумывался о том, что будет, если поменять количество столбцов в сетке. Давайте поменяем количество колонок, задав 5 для функции repeat().
.awesome-container {
display: grid;
grid-template-columns: repeat(5, 1fr);
box-sizing: border-box;
min-height: 50dvh;
border: 4px solid purple;
}
.awesome-block {
grid-column: 2 / span 2;
background-color: pink;
}

Да, элемент перестал занимать всё пространство. И это абсолютно правильно. Мы же говорим браузерам, что элемент занимает две колонки, начиная со второй. Они это и сделали.
Если вы делаете так же, то для вас у меня есть новое решение. Я напомню, что, кроме ключевого слова span, есть альтернативный способ установки координат элементов. Мы можем указать стартовую позицию, а через слэш — последнюю.
Вот второе значение может быть отрицательным. В этом случае браузеры рассчитают координату с конца. Например, значение -1 говорит им, что элемент будет занимать все колонки до последней.
.awesome-container {
display: grid;
grid-template-columns: repeat(5, 1fr);
box-sizing: border-box;
min-height: 50dvh;
border: 4px solid purple;
}
.awesome-block {
grid-column: 2 / -1;
background-color: pink;
}

При таком варианте абсолютно всё равно на количество объявленных колонок. Давайте мы ещё раз поменяем их. Например, сделаем десять.
.awesome-container {
display: grid;
grid-template-columns: repeat(10, 1fr);
box-sizing: border-box;
min-height: 50dvh;
border: 4px solid purple;
}
.awesome-block {
grid-column: 2 / -1;
background-color: pink;
}

Идеальное решение! А ещё и лаконичное. Меня всегда удивляет, почему разработчики про него не слышали. Надеюсь, теперь будете чаще использовать его.
Можно использовать шрифт операционной системы для веб-контента по умолчанию
Согласитесь, без отличной типографики не может существовать крутой интерфейс. Десять лет назад у нас была проблема. Если использовался кастомный шрифт и он не загрузился, то мы видели в лучшем случае шрифт из семейства sans-serif.
body {
font-family: "PT Sans", sans-serif;
}
Или, что ещё хуже, вообще какой-нибудь Times New Roman, когда ключевое слово sans-serif не было объявлено.
body {
font-family: "PT Sans";
}
Сегодня мы можем сделать всё по-другому. Шрифт по умолчанию может быть тоже классным! В этом нам поможет ключевое слово system-ui.
Если вы ранее не слышали о нём, то его задача супер простая. Оно говорит браузерам использовать шрифт, который уже есть в операционной системе. Например, вы его видите, когда заходите в настройки. Согласитесь, что в большинстве случаев он выглядит куда лучше стандартных.
Начать использовать ключевое слово system-ui очень просто. Объявите его после кастомного шрифта.
body {
font-family: "PT Sans", system-ui;
}
Вот так просто типографика вашего проекта будет всегда красивой.
Объявление размеров элементов с установленным свойством position со значением absolute в одну строку
Общаясь с коллегами, заметил одну штуку. Многие используют свойства width и height со значением 100% для элемента с установленным свойством position и значением absolute, если его нужно растянуть на всю ширину и высоту родителя.
.awesome-block {
min-height: 300px;
position: relative;
}
.awesome-block::before {
content: "";
width: 100%;
height: 100%;
background-color: pink;
position: absolute;
top: 0;
left: 0;
}
Да, код рабочий. Но если вы любите минимализм, то я расскажу вам, как его можно сократить. Вместо четырёх свойств мы будем использовать одно!
Поскольку у элемента используется свойство position со значением absolute, то ему можно задать размеры с помощью свойств top, right, bottom и left. А эти свойства уже можно объединить одним свойством inset.
.awesome-block {
min-height: 300px;
position: relative;
}
.awesome-block::before {
content: "";
background-color: pink;
position: absolute;
inset: 0;
}
Как легко понизить специфичность селектора при рефакторинге кода
Интересно, бывает ли у вас так, что страшно изменять селектор. Лично у меня бывало так, что при рефакторинге кода менял, а потом ловил баги. Да так, что сначала всё выглядело отлично, а где-то на другой странице вёрстка ломалась.
Для демонстрации я подготовил задачу. Нам нужно будет поменять значение свойства background-color.
<body>
<div class="awesome-block awesome-box">
<!-- здесь контент -->
</div>
<div class="awesome-block awesome-box new-awesome-block">
<!-- здесь контент -->
</div>
</body>
.awesome-block {
min-height: 200px;
margin: 1rem;
}
.awesome-block.awesome-box {
background-color: tomato;
}
В идеальном мире мне хотелось бы просто написать новый класс с нужным значением. Например, правило с классом .new-awesome-block, который изменит значение для свойства background-color на green.
.awesome-block {
min-height: 200px;
margin: 1rem;
}
.awesome-block.awesome-box {
background-color: tomato;
}
.new-awesome-block {
background-color: green;
/*
К сожалению, это значение уступит значению tomato из-за специфичности
*/
}

Уже давно браузеры хорошо поддерживают CSS-слои. Одна из их вышек заключается в том, что они менее приоритетные, чем обычные стили. Это даёт нам возможность завернуть правило со сложным селектором в слой, и он будет менее специфичным, чем обычный селектор по классу.
В нашем примере мы обернём правило с селектором .awesome-block.awesome-box в слой deprecated.
.awesome-block {
min-height: 200px;
margin: 1rem;
}
@layer deprecated {
.awesome-block.awesome-box {
background-color: tomato;
}
}
.new-awesome-block {
background-color: green; /* теперь это значение выиграло! */
}

Больше никакого страха. Новый класс переопределит старые стили там, где мы его добавим. А в других местах кода ошибок не будет, потому что самого класса нет.
Установка размеров с ограничениями функциями min() и max()
При работе с размерами иногда может потребоваться ограничить значения с помощью свойств min-width, max-width, min-height.
Например, растянуть весь блок, но чтобы он не был больше 1200px.
.awesome-block {
width: 100%;
max-width: 1200px;
}
Ничего сложного. Уверен, вы использовали этот код множество раз. Только у меня есть предложение. А давайте сократим этот код до одной строки?
Существуют математические функции min() и max(). Они позволяют браузерам выбрать значение из нескольких переданных. Функция min() найдёт минимальное, а функция max() максимальное.
В нашем примере я буду использовать первую.
.awesome-block {
width: min(100%, 1200px);
}
Объясню, как работает код. Значение 100% будет рассчитано в пикселях. Пока оно меньше 1200px, браузеры будут выбирать его. Как только оно станет больше, то они выберут 1200px.
Для полной демонстрации покажу функцию max().
.awesome-block {
width: max(100%, 1200px);
}
/*
это код аналогичен следующему:
.awesome-block {
width: 100%;
min-width: 1200px;
}
*/
Принцип работы почти такой же. Разница только в том, что когда 100% будут соответствовать значению, большему 1200px, то браузеры станут всегда использовать последнее.
Если вам непривычно ориентироваться в математических функциях min() и max(), можно упростить их восприятие с помощью пользовательских CSS-свойств.
.awesome-block {
width: min(var(--current-width, 100%), var(--max-width, 1024px));
}
.awesome-block {
width: max(var(--current-width, 100%), var(--min-width, 1024px));
}
Лично я именно так устанавливаю размеры. Но можно и без пользовательских свойств или продолжить писать свойства по старинке. Критических ошибок не будет. Тут уже дело вкуса!
Стартовый экран на мобильных устройствах может занимать всё пространство без проблем
При адаптивной вёрстке часто есть потребность растянуть стартовый экран на всю высоту вьюпорта. Когда появились единицы измерения vh, у меня была надежда.
«Теперь можно легко сделать стартовый экран на всю высоту», — подумал я. Реальность была жестокой...
.awesome-block {
min-height: 100vh;
}
Нюанс заключается в том, что стартовый экран растянется больше, чем на всю высоту. При расчёте значения будет учтена высота поисковой панели браузера.
Эх, а столько было надежд! В итоге мне пришлось отказаться от единиц измерения vh и решать задачу старым способом.
Сегодня есть другое решение. Можно использовать единицы измерения dvh.
.awesome-block {
min-height: 100dvh;
}
Браузеры уже рассчитают значения без учёта поисковой панели. Элемент растянется на весь экран без проблем. Ура!
Заключение
Давайте подведём итог. В этой статье мы рассмотрели:
способ растягивания дочерних элементов внутри CSS-гридов без зависимости от количества объявленных колонок;
ключевое слово
system=ui, позволяющее использовать красивый шрифт операционной системы для веб-контента по умолчанию;трюк по растягиванию элемента на всю ширину и высоту родителя с помощью свойства
inset;математические функции
min()иmax()для сокращения кода, в котором происходит установка размеров с ограничениями;способ растянуть стартовый экран на всю высоту с помощью единиц измерения
dvh;как при рефакторинге кода можно понизить специфичность «страшного» селектора без боязни всё поломать.
На этом всё. Спасибо за чтение!
P. S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
© 2025 ООО «МТ ФИНАНС»
monochromer
Я для этого использую
:where. Например,.selector:where(.selector) {}