Псевдоэлементы - мощный инструмент для создания дополнительной стилизации элементов. В этой статье посмотрим, для чего их можно использовать и как.
Что такое псевдоэлементы и зачем они нужны
Это дополнения к элементам, которые создаются с помощью CSS. Они не размещаются в разметке, но, если заглянуть в DevTools, их можно найти в разделе Elements.
Использовать псевдоэлементы можно для самых разных целей. Описать все - не хватит и объема небольшой книги, не то что статьи. Так что в этом материале я хочу рассмотреть два полезных псевдоэлемента - ::before и ::after
По умолчанию, псевдоэлементы ::before и ::after делают то, что должны - добавляют нечто до элемента и после элемента. Однако, на практике почти никто не использует эту возможность, т.к. потребность в ней возникает крайне редко. Ниже я расскажу о десяти способах реального использования данных псевдоэлементов в работе.
Иконки для элементов
С помощью псевдоэлементов можно сделать иконки для элементов. Например, для ссылки с телефоном нужно добавить иконку-трубку. Вот простой пример использования этой возможности.
<a href="tel:+79999999999">+7 (999) 999-9999</a>
.link {
display: inline-flex;
align-items: center;
text-decoration: none;
}
.link--phone::before {
content: "";
display: inline-block;
margin-right: 10px;
width: 1em;
height: 1em;
background-image: url("https://cdn-icons-png.flaticon.com/512/597/597177.png");
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
Тут все просто: указываем размеры, дисплей, отступ, а также саму иконку - с помощью background. И самое важное - это свойство content. Да, здесь оно со значением пустой строки (и будет таким почти во всех примерах), однако без него псевдоэлементы вообще не появятся.
У предложенного решения два плюса: мы вынесли иконку в CSS, чем разгрузили разметку, а также создали отдельный класс .link--phone, который всегда будет добавлять эту иконку, если надо.
Поиграть с этим кодом можно по ссылке.
2.Счетчики на элементах
Нередко в дизайне сайтов встречается набор элементов, которые имеют порядковый номер: 01, 02, 03, 04 и т.п. Представьте, что количество таких элементов каждый день растет, объем контента сайта увеличивается, и с каждым новым блоком вам придется вручную писать каждую цифру. Это крайне неудобно, так что для это цели придумали счетчики, которые реализуются как раз с помощью псевдоэлементов. Давайте разберем на примере:
<div class="parent">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
.parent {
width: 1000px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
gap: 30px;
counter-reset: numbers
}
.block {
position: relative;
min-height: 300px;
width: 30%;
border: 1px solid #000;
}
.block::after {
position: absolute;
right: 10px;
bottom: 10px;
counter-increment: numbers;
content: counter(numbers);
}
Здесь нас интересует несколько вещей. Во-первых, для родителя итерируемых элементов (в нашем случае div с классом parent) мы задаем свойство counter-reset. Это, по сути, имя нашего счетчика, который мы далее будем использовать. Можно сюда написать что угодно по смыслу, в нашем случае будет numbers.
Далее, у самих элементов нужно создать псевдоэлемент (before или after - неважно, т.к. мы используем абсолютное позиционирование), и указать в нем два свойства:
counter-increment: numbers - здесь мы указываем, что значение будет инкриментировано (будет увеличиваться), и название будет то же, что и у counter-reset
content: counter(numbers) - а здесь запускаем счетчик с помощью CSS-функции counter. Теперь это число будет увеличиваться в зависимости от количества блоков.
Если ваше число должно отличаться особым образом, например не “1, 2, 3”, а “01, 02, 03”, вы можете модернизировать свойство content, напрямую добавив в него число 0. Например: content: “0” counter(numbers).
Вы можете поиграть с примером по ссылке.
3.Кастомные чекбоксы и радиокнопки
Как известно, стилизация чекбоксов и радиокнопок - дело непростое. Напрямую стилизовать их нельзя, так что приходится использовать обходные пути. Один из таких путей - использование псевдоэлемента. Посмотрим на пример:
<label class="checkbox">
<input type="checkbox" class="checkbox__input">
<span class="checkbox__text">Фильтр</span>
</label>
.checkbox {
user-select: none;
position: relative;
cursor: pointer;
}
.checkbox__text {
padding-left: calc(1em + 10px);
}
.checkbox__input {
-webkit-appearance: none;
appearance: none;
}
.checkbox__input::before {
content: '';
cursor: pointer;
position: absolute;
top: -2px;
left: 0;
width: 1em;
height: 1em;
border: 3px solid crimson;
border-radius: 100%;
}
.checkbox__input:checked::before {
background: crimson;
}
Самое важное - стили инпута и его псевдоэлемента. Сперва мы задаем инпуту appearance: none, внешне скрывая стандартный чекбокс. Затем с помощью псевдоэлемента рисуем простой кружок с бордером. И только когда чекбокс в состоянии checked (то есть нажат, активен), применяем дополнительный стиль, задаем фон кружочку.
Вы можете поиграть с примером по ссылке.
4.Обводка с градиентом
Сделать градиент через свойство border крайне трудно, а в некоторых браузерах просто невозможно. Но и здесь можно обойти систему, использовав псевдоэлементы. Посмотрим пример:
<div class="image">
<img src="https://www.xaprb.com/media/2018/08/kitten.jpg" alt="Спящий кот">
</div>
.image {
position: relative;
padding: 5px;
width: 400px;
}
img {
max-width: 100%;
}
.image::before {
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-image: linear-gradient(crimson, yellow);
z-index: -1;
}
Тут мы имитируем бордер с помощью градиентного фона, и наложенного поверх него изображения. Благодаря паддингу в 5 пикселей картинка сжимается, а фон под ней проявляется как раз на 5 пикселей с каждой стороны. Внешне это очень похоже на обводку элемента.
Вы можете поиграть с примером по ссылке.
5.Кастомные иконки у списка
Через псевдоэлемент можно делать и кастомные иконки для списков. Вы можете использовать даже эмоджи, если это требуется.
<ul class="list">
<li>Элемент 1</li>
<li>Элемент 2</li>
<li>Элемент 3</li>
<li>Элемент 4</li>
</ul>
.list {
list-style: none;
}
.list li::before {
content: "