За последнее время в CSS появилось достаточно новых возможностей, которые позволяют нам создавать новые решения для старых задач. Мне захотелось рассказать вам о тех, которые работают в современных браузерах, и их можно использовать прямо сейчас.
Я подобрал, как мне кажется, наиболее распространенные задачи и покажу вам, как они решаются с помощью современного CSS. Надеюсь, вам будет интересно, и вы узнаете что-то новое. Так что не буду задерживаться, давайте начнем.
Функции min() и max()
Я уверен, что периодически вам приходится делать элемент растягивающийся на всю ширину родителя, а также ограничивать его максимальный размер. Часто реализация этой задачи выглядит следующим образом:
.container {
width: 100%;
max-width: 1024px;
}
Это надежный фрагмент кода, проверенный временем. Но у меня есть идея, как его сократить до одной строки. Для этого нам нужно использовать математическую функцию min()
. Данная функция позволяет браузеру выбрать наименьшее значение из представленных аргументов.
Возвращаясь к нашему примеру, мы хотим, чтобы браузер выбирал всегда значение 100%
, пока данное значение не станет больше 1024px
. Соответственно, нам остается передать значения 100%
и 1024px
.
.container {
width: min(100%, 1024px);
}
Но если мы укажем аргументы в обратном порядке, то проблем не будет, потому что у нас есть возможность указывать их в любом порядке. Так что следующий фрагмент кода даст такой же результат, что и предыдущий.
.container {
width: min(1024px, 100%);
}
Но лично мне нравится сначала указать ширину, а только потом максимальное значение, поэтому я за первый вариант! Но если вам нравится второй, то тоже все отлично.
Ой! Чуть не забыл рассказать, что кроме функции min()
, есть еще функция max()
. Данная функция напоминает функцию min()
, разница только в том, что вместо минимального значения браузеры выбирают максимальное.
Функцию max()
можно использовать для установки минимального размера. Конечно, это требуется реже, чем в случаях с установкой максимального размера, но все же такая задача случается.
Давайте рассмотрим пример, где мы делаем элемент, растягивающийся на всю ширину родителя, но имеющий минимальную ширину 1024px
:
.container {
width: 100%;
min-width: 1024px;
}
По аналогии с функцией min()
, его можно сократить до одной строки с помощью функции max()
:
.container {
width: max(100%, 1024px);
}
Класс! Установка размеров теперь может выглядеть так кратко. По этой причине я, недолго думая, перешел на использование функций min()
и max()
.
А еще функции можно комбинировать с CSS Custom Properties, и можно написать вот такой код:
.container {
width: min(var(--current-width, 100%), var(--max-width, 1024px));
}
.container {
width: max(var(--current-width, 100%), var(--min-width, 1024px));
}
Но это уже дело вкуса. Просто я люблю использовать CSS Custom Properties, и поэтому поделился с вами этой фишкой. Может быть, кому-то она понравится.
Браузерная поддержка: Edge, Firefox, Chrome, Opera, Safari, iOS Safari, Android Browser, Chrome Android, Samsung Internet по данным Can I use.
Свойство inset
При использовании position: absolute
или position: fixed
иногда приходится растягивать элемент на всю ширину и высоту. Например, использование свойств top
, right
, bottom
и left
— это один из популярных способов решения данной задачи.
.item {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
Если вы фанат этого метода, то для вас у меня хорошие новости. Мы можем сократить этот код до 2 свойств! В этом на поможет свойство inset
.
Свойство inset
— это шорткат, задающий значение для свойств top
, right
, bottom
и left
, с помощью которого значения отступов будут автоматически подстроены в зависимости от направления текста на разных языках. Я не буду вдаваться в подробности, потому что в нашей задаче это излишне.
Самое главное, что свойство поможет нам одновременно задать значение для отступов со всех сторон. В качестве примера я перепишу предыдущий фрагмент кода, где мы задали 0
в качестве значения.
.item {
position: absolute;
inset: 0;
}
Представляете, как просто? А для полной картины я хочу показать вам второй способ решения задачи, основанный на том, что нам требуется задать значение 100%
для свойств width
и height
.
.item {
position: absolute;
width: 100%;
height: 100%;
}
Такой фрагмент кода также может быть сокращен до двух строк с помощью свойства inset
.
.item {
position: absolute;
inset: 0;
}
Я теперь каждый раз кайфую, когда пишу такой код и вспоминаю, что теперь не надо писать еще три дополнительных строки. Давайте использовать свойство inset
чаще.
Браузерная поддержка: Edge, Firefox, Chrome, Opera, Safari, iOS Safari, Android Browser, Chrome Android, Samsung Internet по данным Can I use.
Свойство gap
Установка отступов между элементами, например, в горизонтальном меню, одна из самых типичных задач верстальщика. Существует множество решений, и я собрал все, которые попадались в моей практике:
/* решение №1 */
.list {
display: flex;
}
.list__item {
margin-right: 16px;
}
.list__item:last-child {
margin-right: 0;
}
/* решение №2 */
.list {
display: flex;
}
.list__item:not(:last-child) {
margin-right: 16px;
}
/* решение №3 */
.list {
display: flex;
}
.list__item + .list__item {
margin-left: 16px;
}
/* решение №4 */
.list {
display: flex;
}
.list__item:nth-child(n+2) {
margin-left: 16px;
}
Я был фанатом четвертого подхода и спорил со всеми о том, что он лучший. Особенно лучше первого. Но CSS не стоит на месте, и поэтому я хочу предложить еще один подход, который лучший. Да, да.. Вы можете в комментариях пошутить на эту тему. В общем, как вы уже поняли по заголовку раздела, я имею в виду свойство gap
.
Свойство gap
— это шорткат для записи значений свойств row-gap
и column-gap
. Первое задает отступ между элементам, а второе — между столбцами. Сначала свойство gap
работало только вместе с гридами, а потом стало поддерживаться всеми браузерами для флексбоксов. После этого момента я предлагаю использовать его вместо свойства margin
.
Для демонстрации преимущества свойства я с его помощью сокращу код всех предыдущих решений до следующего:
.list {
display: flex;
gap: 16px;
}
Вот так лаконично. Так что я больше не могу использовать решения со сложными селекторами и свойством margin
. Свойство gap
— мой фаворит. А чтобы оно стало и вашим, я покажу еще один пример, где свойство gap
прекрасно себя показывает.
Давайте представим, что нам нужно сверстать интерактивный элемент, у которого может быть несколько состояний. Первое состояние — это только текст без иконки, второе — иконка, находящаяся перед текстом, третье — иконка, находящаяся после текста, а четвертое — иконка без текста.
Чтобы учесть все требования, нам нужно создать несколько классов, которые будут задавать отступ между текстом и иконкой, но также они не должны конфликтовать с состояниями «один» и «четыре». Поэтому для состояния «два» мы будем использовать дополнительный класс .button__icon--pos-before
, а для состояния «три» — .button__icon--pos-after
.
<!-- состояние №1: только текст без иконки -->
<button type="button" class="button">
<span class="button__text">Перейти</span>
</button>
<!-- состояние №2: иконка находящийся перед текстом -->
<button type="button" class="button">
<svg class="button__icon button__icon--pos-before" width="16" height="16" viewbox="0 0 24 24">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
</svg>
<span class="button__text">Перейти</span>
</button>
<!-- состояние №3: иконка находящийся после текста -->
<button type="button" class="button">
<span class="button__text">Перейти</span>
<svg class="button__icon button__icon--pos-after" width="16" height="16" viewbox="0 0 24 24">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
</svg>
</button>
<!-- состояние №4: только иконка -->
<button type="button" class="button" aria-label="Перейти">
<svg class="button__icon" width="16" height="16" viewbox="0 0 24 24">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
</svg>
</button>
.button {
display: inline-flex;
}
.button__icon--pos-before {
margin-right: 8px;
}
.button__icon--pos-after {
margin-left: 8px;
}
Именно так решалась данная задача до появления свойства gap
, а теперь можно просто сделать то же самое с помощью него.
<!-- состояние №1: только текст без иконки -->
<button type="button" class="button">
<span class="button__text">Перейти</span>
</button>
<!-- состояние №2: иконка находящийся перед текстом -->
<button type="button" class="button">
<svg class="button__icon" width="16" height="16" viewbox="0 0 24 24">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
</svg>
<span class="button__text">Перейти</span>
</button>
<!-- состояние №3: иконка находящийся после текста -->
<button type="button" class="button">
<span class="button__text">Перейти</span>
<svg class="button__icon" width="16" height="16" viewbox="0 0 24 24">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
</svg>
</button>
<!-- состояние №4: только иконка -->
<button type="button" class="button" aria-label="Перейти">
<svg class="button__icon" width="16" height="16" viewbox="0 0 24 24">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
</svg>
</button>
.button {
display: inline-flex;
gap: 8px;
}
Все! Мы удалили классы .button__icon--pos-before
и .button__icon--pos-after
, потому что браузер сам установит отступ там, где нужно. А если у нас состояние только с иконкой, то вообще не установит. Нам ничего дополнительно делать не нужно. Красота?!
Браузерная поддержка: Edge, Firefox, Chrome, Opera, Safari, iOS Safari, Android Browser, Chrome Android, Samsung Internet по данным Can I use.
Свойства margin-inline, margin-block, padding-inline и padding-block
При разработке приложений встречаются ситуации, когда приходится использовать 0
для свойств margin
и padding
, чтобы задать значения сразу для двух сторон. Например, я задам значение 10px
сверху и 15px
снизу для свойств margin
и padding
.
.container {
margin: 10px 0 15px;
padding: 10px 0 15px;
}
Мне кажется, если вы перфекционист, то где-то в душе вы поймете меня. Каждый раз, когда мне приходилось писать такой код, я был в печали. Ведь задавать 0
нелогично! Мне приходится задавать значение там, где не нужно. Вот такие тараканы бывают у верстальщика после 9 лет верстки. Славу богу, что появились свойства margin-inline
, margin-block
, padding-inline
и padding-block
.
По аналогии со свойством inset
данные свойства задают внешний и внутренний отступ для элемента в зависимости от направления текста. Для кириллицы и латиницы с помощью свойства margin-inline
и padding-inline
мы задаем отступы слева и справа, а свойства margin-block
и padding-block
— сверху и снизу.
Таким образом, предыдущий фрагмент кода можно переписать вот так:
.container {
margin-block: 10px 15px;
padding-block: 10px 15px;
}
Ох, вот смотрю на этот код, и мой внутренний перфекционист радуется! Теперь все логично. А еще я не мог упустить момента, чтобы показать, где еще не нужно использовать 0
.
Раньше, когда мы создавали блок, который центрирует содержимое страницы, нам приходилось использовать следующий фрагмент кода:
.container {
max-width: 1024px;
margin: 0 auto;
padding: 0 10px;
}
А теперь мы можем заменить его кодом с использованием свойств margin-inline
и padding-inline
:
.container {
max-width: 1024px;
margin-inline: auto;
padding-inline: 10px;
}
Моя душа спокойна. Если вас также раздражал 0
, как и меня, то теперь вы знаете, что с этим делать.
Браузерная поддержка: Edge, Firefox, Chrome, Opera, Safari, iOS Safari, Android Browser, Chrome Android, Samsung Internet по данным Can I use.
Заключение
Хочется верить, что рассказанные мной техники вам понравились, и вы задумаетесь над тем, как их использовать. Если я что-то забыл, то, пожалуйста, напишите об этом. Мне будет интересно почитать!
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.