Что такое псевдоэлементы в CSS и что интересного можно с ними сделать
easy

Что такое псевдоэлементы в CSS и что интересного можно с ними сделать

Они видны на странице, но их нет в HTML

С помощью CSS-стилей на сайте можно делать много полезного и красивого: выравнивать элементы, добавлять тени, плавные переходы и анимации, создавать элементы необычной формы — и всё это без изменения HTML-разметки. А ещё есть псевдоэлементы — это как бы стили для стилей, но без стилей. Если освоить их — всё, вы прошли всю вёрстку, ничего более сложного в CSS уже не будет. В общем, про это сегодня и поговорим.

Что такое псевдоэлементы в CSS

Псевдоэлементы в CSS — это способ видоизменять определённые части реальных HTML-элементов, не указывая стили в самой разметке. С помощью псевдоэлементов можно добавить что-то перед элементом, после него или изменить стиль первого символа или строки. 

По сути, это дополнительный слой на странице. Когда браузер читает CSS-файл и доходит до псевдоэлемента, то вставляет фантомный элемент на страницу, как если бы увидел такое указание в HTML-файле. То есть псевдоэлемента как бы нет на самом деле, но браузер может с ним работать так, будто он есть.

С помощью псевдоэлементов можно добавлять разные декоративные штуки, не усложняя структуру документа. Забавы ради представим, что нам нужно добавить жирную синюю стрелку перед началом каждого абзаца в тексте. Если делать это стандартными средствами, то нам понадобится указать стиль стрелки в CSS:

/* задаём стиль стрелки */
.decorator {
    /* синий цвет */
    color: blue;
    /* жирное начертание */
    font-weight: bold;
}

А затем добавить символ стрелки в HTML-разметку к каждому абзацу:

<!-- добавляем стрелку с соответствующим стилем к абзацу -->
<p><span class="decorator">→</span> Это первый абзац с декоративной стрелкой перед ним.</p>

<!-- добавляем стрелку с соответствующим стилем к абзацу -->
<p><span class="decorator">→</span> Это второй абзац с декоративной стрелкой перед ним.</p>

Теперь сделаем то же самое с помощью псевдоэлемента в CSS:

/* добавляем элемент перед каждым абзацем */
p::before {
    /* указываем элемент */
    content: "→";
    /* синий цвет */
    color: blue;
    /* жирное начертание */
    font-weight: bold;
    /* отступ после элемента */
    margin-right: 5px;
}

Но в HTML нам ничего добавлять не нужно, потому что с псевдоэлементом стрелка и так появится перед каждым абзацем. В итоге разметка страницы стала чище, а вся магия происходит как бы сама по себе:

<p>Это первый абзац с декоративной стрелкой перед ним.</p>
<p>Это второй абзац с декоративной стрелкой перед ним.</p>

Синтаксис псевдоэлементов

В спецификации описаны четыре псевдоэлемента, которые используются в современной вёрстке:

  • ::before добавляет контент перед содержимым элемента.
  • ::after добавляет контент после содержимого элемента.
  • ::first-line применяет стили к первой строке текста в элементе.
  • ::first-letter применяет стили к первой букве текста в элементе.

Псевдоэлемент задаётся через двойное двоеточие после селектора:

.div::pseudoelement {
  /* стили */
}

Элементы ::before и ::after задаются через свойство content. При этом достаточно даже пустой строки в значении свойства — content: "".

.div::after {
content: ""
}

👉 По умолчанию псевдоэлементы ::before и ::after — inline-элементы, как <span> и <a>, то есть их содержимое отображается на одной строке с остальным текстом. Если нужно, чтобы ::before и ::after вели себя как блочные элементы, можно задать свойство display: block;. Тогда контент этих псевдоэлементов будет начинаться с новой строки и занимать всю ширину. 

Для чего нужны псевдоэлементы

Псевдоэлементы ::before и ::after часто используются для добавления декоративных элементов без изменения HTML-кода.

Например, с помощью ::before  легко сделать свои маркеры в списках. Для этого нужно отключить стандартное форматирование маркеров и добавить стиль для псевдоэлемента. Добавим свой маркер в виде эмодзи списку small-list:

.small-list {
    /* отключаем стандартные маркеры */
    list-style-type: none; 
    padding: 0;
}
.small-list li {
  /* позиционируем относительно элементов списка */
  position: relative; 
}
.small-list li::before {
  /* добавляем содержимое псевдоэлемента */
  content: '🤯'; 
  /* позиционируем псевдоэлемент */
  position: absolute; 
  /* размещаем эмодзи слева от текста, выравнивая с его началом */
  left: -1.5em; 
/* выравниваем по верху элемента списка */
  top: 0; 
}

Псевдоэлементы ::first-line и ::first-letter позволяют стилизовать первую строку или первую букву параграфа. В CSS-правилах нужно использовать только свойства, относящиеся к шрифту, изменению цвета текста и фона. 

Для примера стилизуем первую букву в заголовке статьи в «Коде». Обычно заголовки наших статей выглядят как-то так:

Теперь мы добавим к селектору заголовка псевдоэлемент ::first-letter и пропишем его свойства:

/* стилизуем первую букву */
.post__title::first-letter {
  /* размер шрифта */
  font-size: 66px;
  /* жирное начертание */
  font-weight: bold;
  /* цвет */
  color: #ff6347;
  /* отступ справа */
  padding-right: 2px;
  /* высота строки */
  line-height: 1;
  /* семейство шрифтов */
  font-family: "Courier New", Courier, monospace;
}

Вот что получилось. Красота же:

Аналогично можно добавить стили первой строке текста с помощью ::first-line. Псевдоэлемент будет действовать на строку так, как она отображается в браузере, и изменяться в зависимости от ширины контейнера и размеров шрифта:

/* стилизуем первую строку */
.post__title::first-line {
  /* размер шрифта */
  font-size: 66px;
  /* жирное начертание */
  font-weight: bold;
  /* цвет */
  color: #ff6347;
  /* семейство шрифтов */
  font-family: "Courier New", Courier, monospace;
  /* сделать заглавными */
  text-transform: uppercase;
}

Выглядит уже слишком агрессивно, поэтому применяйте с умом:

Это базовые варианты использования псевдоэлементов. Но на самом деле с ними можно делать много других интересных штук: рисовать фигуры, добавлять сложные украшения, играться со шрифтами, делать анимации и интересные ховер-эффекты — и всё это без изменения основного кода и структуры документа.

Например, мы уже писали о том, как сделать у текста глитч-эффект. И вся суть глитч-эффекта там реализована именно через псевдоэлементы. 

Рисуем фигуры, используя псевдоэлементы

С псевдоэлементами можно рисовать разные фигуры: сердечки, звёзды, кристаллы, изогнутые стрелки или что-то посложнее.

Для примера нарисуем в CSS сердечко. Фишка в том, что мы просто создаём обычный квадрат, переворачиваем его, а недостающие детали сердца рисуем уже с помощью псевдоэлементов:

Делаем контейнер для фигуры:

 <div class="heart"></div>

Задаём стили:

/* стиль основной части сердца */
.heart {
  /* относительное позиционирование */
  position: relative;
  /* ширина */
  width: 100px; 
  /* высота */
  height: 100px;
  /* цвет фона */
  background-color: red;
  /* поворот на 45° */
  transform: rotate(-45deg); 
  /* отступ */
  margin: 50px;
}

/* псевдоэлементы, создающие верхние части сердца */
.heart::before,
.heart::after {
  content: ""; 
  /* позиционируем относительно родительского элемента */
  position: absolute; 
  /* ширина круга, равная ширине квадрата */
  width: 100px; 
  /* высота круга, равная высоте квадрата */
  height: 100px; 
  /* цвет фона */
  background-color: red; 
  /* создаём круги из псевдоэлементов */
  border-radius: 50%; }

/* позиционируем левый верхний круг */
.heart::before {
  /* перемещаем круг вверх на 50 пикселей, выравнивая его с верхним краем сердца */
  top: -50px; 
  /* устанавливаем круг на левую границу родительского элемента */
  left: 0; 
}

/* позиционируем правый верхний круг */
.heart::after {
  /* оставляем круг на уровне верхнего края родительского элемента */
  top: 0; 
  /* перемещаем круг вправо на 50 пикселей, выравнивая его с правым краем сердца */
  left: 50px; 
}

Вот что получилось:

Если мы проверим наш контейнер heart в web-инспекторе браузера, то увидим, что сердце как будто состоит из трёх элементов (что, по сути, так и есть):

Анимации с псевдоэлементами

Теперь добавим кнопке красивую анимацию, которая будет запускаться при наведении курсора. Для этого нам понадобится градиентный слой в псевдоэлементе ::after, который при наведении курсора будет сдвигаться и вращаться.

Сделаем основной стиль для кнопки:

button {
  /* цвет фона */
  background: #ff32d3;
  /* цвет кнопки */
  color: #fff;
  /* размер шрифта */
  font-size: 14px;
  /* скругление углов */
  border-radius: 0.5em;
  /* без рамки */
  border: none;
  /* отступы */
  padding: 0 1em;
  /* относительное позиционирование */
  position: relative;
  /* скрываем всё, что выходит за границы */
  overflow: hidden;
  /* высота строки */
  line-height: 32px;
}

Теперь добавим псевдоэлемент, где нарисуем градиент:

button::after {
  content: ""; 
  position: absolute; 
  top: -50%; 
  right: -50%; 
  bottom: -50%;
  left: -50%;
  background: linear-gradient(
    /* направление градиента сверху вниз */
    to bottom, 
    /* прозрачный цвет в начале градиента */
    rgba(229, 172, 142, 0), 
    /* белый цвет с прозрачностью 0,5 в середине градиента */
    rgba(255, 255, 255, 0.5) 50%, 
    /* прозрачный цвет в конце градиента */
    rgba(229, 172, 142, 0) 
  );
  /* вращаем и сдвигаем псевдоэлемент */
  transform: rotateZ(60deg) translate(-5em, 7.5em); 
}

button:hover::after,
button:focus::after {
  /* применяем анимацию при наведении или фокусе */
  animation: sheen 1s forwards; 
}

Создадим анимацию, где будет изменяться положение псевдоэлемента:

@keyframes sheen {
  100% {
    transform: rotateZ(60deg) translate(1em, -9em); 
  }
}

Вот что получилось:

Рамка с градиентом

Ну и напоследок добавим к контейнеру рамку с градиентом. Через псевдоэлемент ::before мы создаём отдельный градиентный слой и помещаем его ниже того слоя, которому хотим добавить рамку. 

На странице журнала «Код» есть контейнер со статьёй post.post--wide. Добавим ему псевдоэлемент в виде рамки:

div.post.post--wide::before {
  content: ""; 
  position: absolute;
  /* сдвигаем верхнюю границу выше на 10 пикселей */
  top: -10px; 
  /* сдвигаем левую границу на 10 пикселей */
  left: -10px; 
  /* сдвигаем нижнюю границу на 10 пикселей */
  bottom: -10px; 
  /* сдвигаем правую границу на 10 пикселей */
  right: -10px; 
  /* задаём линейный градиент фона, переходящий от тёмного к синему цвету */
  background-image: linear-gradient(#1a1a1a, #1560bd); 
  /* перемещаем псевдоэлемент на задний план, чтобы он находился под содержимым элемента .post.post--wide */
  z-index: -1; 
  border-radius: 90px; 
}

Вот что получилось в результате:

Редактор:

Инна Долога

Обложка:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Маша Климентьева

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Еще по теме
easy
[anycomment]
Exit mobile version