Как использовать CSS ::before и ::after для создания пользовательских анимаций и переходов

Kate

Administrator
Команда форума
Как сделать плавный анимированный переход на сайте без использования специальных библиотек? Урок использования псевдоэлементов CSS для создания эффектов: от анимированной кнопки до карточки профиля. Подходит новичкам.

Чтобы применить на практике методы из статьи, нужно:

  • Базовое понимание HTML.
  • Базовое понимание CSS.
  • Редактор кода и браузер.

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

Псевдоэлементы — это селекторы CSS , которые используют для вставки содержимого, которого нет в исходном коде, их используют для стилизации определённой части выбранного элемента. Начинаются они с двойного двоеточия: ::before, ::after, ::placeholder, ::first-letter. В этой статье речь пойдёт только про использование ::before и ::after.

Псевдоэлемент ::before вставляет содержимое перед элементом.

h1::before {
content: "😀";
}
566b9b61cb91028754bd3741ff2de0bd.jpg

Псевдоэлемент ::after вставляет содержимое после элемента.

h1::after{
content: "";
}
2deea934a403fc051f4c8ffbdbbe213b.jpg

В чём разница между псевдоэлементом и псевдоклассом?​

Псевдоэлементы и псевдоклассы иногда путают, потому что звучат они похоже, хотя по факту — совершенно разные явления.

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

Синтаксически псевдокласс начинается с двоеточия, а псевдоэлемент — с двойного двоеточия.

Как создать анимацию при помощи псевдоэлементов​

Скорее всего, вы уже знакомы со многими свойствами CSS. На всякий случай здесь мы сначала рассмотрим некоторые из них.

  • transform
    • translate
    • rotate
    • scale
    • skew
  • transition
  • positioning
  • z-index
Если вы и так знаете о них достаточно, переходите сразу к инструкции.

Transform и Transition​

В этом проекте мы используем свойства transform и transition, так что нужно понимать, что они делают и для чего нужны.

Transform изначально позволяет двигать, поворачивать, масштабировать и наклонять элемент.

.box-1 {
transform: translate(100px, 100px);
}
.box-2 {
transform: rotate(60deg);
}
.box-3 {
transform: scale(2);
}
.box-4 {
transform: skew(-30deg);
}
Свойство transition устанавливает продолжительность изменений, чтобы анимация была плавной.

Позиционирование с помощью relative и absolute​

Существует несколько свойство CSS, которые помогают контролировать поток документа и положение элемента в документе. В этой статье нам будут интересны только relative и absolute.

Значение relative​

Relative позволяет контролировать позицию элемента относительно себя в потоке документа. Например, можно перемещать объект, используя его изначальное положение в качестве точки отсчёта:

.box-2 {
position: relative;
right: 150px;
top: 0;
}
3afb9b3d9dc7933aa604366e97a0afa4.jpg

Как видите, второй бокс сдвигается вправо на 150 пикселей от изначального положения, но это не влияет на поток документа, поскольку пространство, заданное в макете, не меняется.

Значение absolute​

Когда мы задаём элементу значение absolute, CSS удаляет элемент из обычного потока документа, перекрывая другие элементы. Элемент со значением absolute располагается относительно блока со значением позиционирования relative — родительского контейнера.

Когда такого блока рядом нет, в качестве точки отсчёта используется тело документа.

.parent-container {
position: relative;
}
.box-1 {
position: absolute;
left: 20px;
top: 20px;
}
.box-2 {
position: absolute;
right: 50px;
bottom: 40px;
}
0960413a3eda21825e549bf758dcc65d.jpg

Контроль Controlling the stacking order of elements using z-index​

Свойство z-index позволяет накладывать элементы один на другой и менять порядок наложения. Если элемент находится выше по порядку наложения, он появится раньше элемента с низким значением:

.box-1 {
z-index: 1;
}
.box-2 {
z-index: 2;
}
.box-3 {
z-index: 3;
}
.box-4 {
z-index: 4;
}
bc89c19116d306b6fa60ba6a53e02dad.jpg

Z-index работает только с элементами, которые были позиционированы с помощью свойства position. Если у двух элементов одинаковый z-index, сверху будет тот, который стоит последним в разметке HTML.

Создаём анимацию с помощью псевдоэлементов​

Начнём первый проект с создания простой анимированной кнопки, чтобы понять, как использовать псевдоэлементы для анимации.

Создаём тег привязки, который позже применим к кнопке.

<a href="#" class="btn">Hover Me</a>
Вот что выйдет:

d535955f8d5998dc1c53c44f35fce869.png

Переходим к файлу CSS и стилизуем ссылку, чтобы она выглядела, как кнопка.

.btn {
text-decoration: none;
border: 2px solid #764abc;
color: #764abc;
padding: 10px 20px;
border-radius: 25px;
transition: all 1s;
position: relative;
}
Код должен готовить сам за себя — убрали дефолтное подчёркивание, добавили двухпиксельную рамку и перекрасили кнопку в цвет текста. Ещё добавили отступы, чтобы отделить текст от рамки, и скруглили края кнопки при помощи радиуса границы. Добавили длительность перехода — 1 секунду. То есть любое изменение кнопки будет длиться в течение секунда, плавно. Наконец, установили значение relative, потому что внутри кнопки расположим псевдоэлемент. Кнопка станет родительским контейнером, относительно которого будет меняться положение элемента со значением absolute. Вот что получится:

acfaffebea23e48f9b3e6b3e161f670b.jpg

Пора создать в кнопке псевдоэлемент.

.btn::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #764abc;
transition: all 1s;
}
Мы создали псевдоэлемент с пустым свойством content, то есть внутри ничего нет. Позиционирование у него со значением absolute, что удаляет элемент из обычного потока документов так, что он перекрывает кнопку, и устанавливает координаты top и left равными нулю. Так пустой псевдоэлемент прикрепляется к кнопке именно в этих местах.

После устанавливаем ширину и высоту пустого элемента равными 100 % родительского элемента — кнопки.

В итоге мы перекрасили фон псевдоэлемента в цвет кнопки и ещё раз добавили секундный переход. Вот что получится:

c9f8669f7b73d894cd4afc17428624f0.jpg

Как видим, псевдоэлемент перекрывает кнопку — из-за значения absolute свойства position.

Решим эту задачу, используя z-index, чтобы изменить контекст наложения. Расположим псевдоэлемент за кнопкой при помощи отрицательного значения z-index. Затем используем translate, чтобы передвинуть псевдоэлемент влево на -100%.

.btn::before {
/*...previous code */
z-index: -1;
transform: translateX(-100%);
}
Вот что получается:

d95fcd293bf83b696542c5539fc3edb1.jpg

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

.btn:hover::before {
transform: translateX(0);
}
По сути, когда на кнопку наводят курсор, псевдоэлемент возвращается к позиции absolute. Вот результат:

8af9604d0a55748dcb6dcf10f7df790a.gif
.btn:hover {
color: #fff;
}
12be96ad9df24d028177bc9c33531471.gif

Поскольку мы добавили translate к самой кнопке, изменения пройдут плавно.

Последний шаг: применим overflow: hidden к кнопке, чтобы скрыть любой элемент, выходящий за пределы контейнера. Свойство скроет псевдоэлемент, мы увидим его, когда он вернётся в начальную позицию.

.btn {
/*...previous code. */
overflow: hidden;
}
Итоговый вариант:

f658ed67b65722cec8bfbd162e087ea3.gif

Итак, мы создали анимированную кнопку с помощью псевдоэлемента. Полный код тут.

Создаём продвинутую анимацию для профиля с помощью множества псевдоэлементов​

Теперь усложним задачу и сделаем более сложную анимированную карточку профиля, используя уже четыре псевдоэлемента. Сделаем интересный эффект при наведении курсора. Вот что будет в разметке.

<div class="profile-card">
<div class="info">
<h2>John Doe</h2>
<p>Ceo / Founder</p>
</div>
</div>
Мы создали простую карточку div с данными пользователя: именем и должностью.

057418ed3dc2d99d0f3daa48a57da6bb.jpg

Переходим к CSS и изменяем стиль карточки.

.profile-card {
width: 300px;
height: 400px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
display: grid;
place-items: center;
position: relative;
background: url("/image.jpg") no-repeat center center/cover;
}
Мы создали карточку с фиксированной шириной и высотой, поместили содержимое внутрь и расположили его по центру с помощью CSS Grid. Добавили тень по краям, чтобы всё выглядело реалистичнее. Потом установили карточке значение relative, чтобы превратить её в родительский контейнер для псевдоэлементов. В конце добавили по центру фоновую картинку.

8f2becd939b8fb6310467ef803c2384a.jpg

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

.info::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #764abc;
transform: skew(30deg) translateX(100%);
opacity: 0.3;
z-index: -1;
transition: all 0.6s ease;
}
Поскольку у блока info div нет фиксированной ширины и высоты, псевдоэлемент принимает ширину и высоту родительской карточки.

Затем мы наклоняем его на 30 градусов и сдвигаем на 100%. Блок сдвигается вправо. Отрицательный индекс гарантирует, что он останется за текстом. Делаем блок полупрозрачным.

667dd6985317c38394b5f4a179247ee3.jpg

Переходим к следующему псевдоэлементу:

.info::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #764abc;
transform: skew(-30deg) translate(90%);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.7);
opacity: 0.3;
z-index: -1;
transition: all 0.6s ease;
}
Сделали примерно то же, что и раньше, только изменили направление наклона на противоположное и добавили тень блока, чтобы имитировать 3D.

6bb5b6fee1695dde6d24b1c297863a70.jpg

Теперь сделаем так, чтобы при наведении курсора на карточку псевдоэлементы двигались внутрь карточки. Добавим transition для плавной анимации.

.profile-card:hover .info::before {
transform: skew(30deg) translateX(50%);
}
.profile-card:hover .info::after {
transform: skew(-30deg) translateX(40%);
opacity: 0.7;
}
Вот что получится:

cdb5b2b397442282dfb9011a150a9167.gif

Теперь делаем псевдоэлементы для самой карточки.

.profile-card::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #764abc;
opacity: 0.3;
transform: skew(30deg) translate(100%);
transition: all 0.6s ease;
z-index: -1;
}
Всё уже понятно из кода. Повторяем всё то же, что уже делали, просто передвигаем псевдоэлемент ::before вправо на 85 процентов. Затем создаём последний псевдоэлемент и наклоняем его в другую сторону.

.profile-card::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #764abc;
opacity: 0.3;
transform: skew(-30deg) translate(85%);
transition: all 0.6s ease;
z-index: -1;
}
c467e9d87f88933a8b69e59a90693aed.jpg

Как вы уже догадались, при наведении курсора псевдоэлементы сдвигаются внутрь. Но в этот раз траектория будет больше.

.profile-card:hover:before {
transform: skew(30deg) translateX(30%);
}
.profile-card:hover:after {
transform: skew(-30deg) translateX(20%);
}
Карточка почти готова. Установим свойство overflow как hidden, чтобы спрятать всё, что выходит за края.

.profile-card {
/*...previous code. */
overflow: hidden;
}
Получилось:

70e9953617810c2efde97b96f145caf7.gif

Меняем цвет текста на белый и делаем его прозрачным. Когда курсор на карточке, прозрачность убираем, чтобы текст стал видимым.

.info h2, .info p {
color: #fff;
opacity: 0;
transition: all 0.6s;
}
.profile-card:hover .info h2,
.profile-card:hover .info p {
opacity: 1;
}
Итог:

ec9fd80bc8ae872dc2d44551e32fdc2b.gif

Пока всё. Как видим, псевдоэлементы ::before и ::after помогают разработать анимацию.

 
Сверху