Как сделать плавный анимированный переход на сайте без использования специальных библиотек? Урок использования псевдоэлементов CSS для создания эффектов: от анимированной кнопки до карточки профиля. Подходит новичкам.
Чтобы применить на практике методы из статьи, нужно:
Базовое понимание HTML.
Базовое понимание CSS.
Редактор кода и браузер.
Что такое псевдоэлементы
Псевдоэлементы — это селекторы CSS , которые используют для вставки содержимого, которого нет в исходном коде, их используют для стилизации определённой части выбранного элемента. Начинаются они с двойного двоеточия: ::before
, ::after
, ::placeholder
, ::first-letter
. В этой статье речь пойдёт только про использование ::before
и ::after
.
Псевдоэлемент ::before
вставляет содержимое перед элементом.
h1::before {
content: "😀";
}

Псевдоэлемент ::after
вставляет содержимое после элемента.
h1::after{
content: "";
}

В чём разница между псевдоэлементом и псевдоклассом?
Псевдоэлементы и псевдоклассы иногда путают, потому что звучат они похоже, хотя по факту — совершенно разные явления.
Псевдоэлементы добавляют содержимое. В отличие от них, псевдоклассы — это селекторы, которые выбирают элементы, находящиеся в определённом состоянии. Пример — псевдокласс :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;
}

Как видите, второй бокс сдвигается вправо на 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;
}

Контроль 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;
}

Z-index
работает только с элементами, которые были позиционированы с помощью свойства position
. Если у двух элементов одинаковый z-index
, сверху будет тот, который стоит последним в разметке HTML.
Создаём анимацию с помощью псевдоэлементов
Начнём первый проект с создания простой анимированной кнопки, чтобы понять, как использовать псевдоэлементы для анимации.
Создаём тег привязки, который позже применим к кнопке.
<a href="#" class="btn">Hover Me</a>
Вот что выйдет:

Переходим к файлу 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
. Вот что получится:

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

Как видим, псевдоэлемент перекрывает кнопку — из-за значения absolute
свойства position
.
Решим эту задачу, используя z-index
, чтобы изменить контекст наложения. Расположим псевдоэлемент за кнопкой при помощи отрицательного значения z-index
. Затем используем translate
, чтобы передвинуть псевдоэлемент влево на -100%.
.btn::before {
/*...previous code */
z-index: -1;
transform: translateX(-100%);
}
Вот что получается:

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

.btn:hover {
color: #fff;
}

Поскольку мы добавили translate
к самой кнопке, изменения пройдут плавно.
Последний шаг: применим overflow: hidden
к кнопке, чтобы скрыть любой элемент, выходящий за пределы контейнера. Свойство скроет псевдоэлемент, мы увидим его, когда он вернётся в начальную позицию.
.btn {
/*...previous code. */
overflow: hidden;
}
Итоговый вариант:

Итак, мы создали анимированную кнопку с помощью псевдоэлемента. Полный код тут.
Создаём продвинутую анимацию для профиля с помощью множества псевдоэлементов
Теперь усложним задачу и сделаем более сложную анимированную карточку профиля, используя уже четыре псевдоэлемента. Сделаем интересный эффект при наведении курсора. Вот что будет в разметке.
<div class="profile-card">
<div class="info">
<h2>John Doe</h2>
<p>Ceo / Founder</p>
</div>
</div>
Мы создали простую карточку div
с данными пользователя: именем и должностью.

Переходим к 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
, чтобы превратить её в родительский контейнер для псевдоэлементов. В конце добавили по центру фоновую картинку.

Переходим к созданию псевдоэлементов. Это непросто. Нужно использовать четыре псевдоэлемента, но у элемента может быть только один псевдоэлемент ::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%. Блок сдвигается вправо. Отрицательный индекс гарантирует, что он останется за текстом. Делаем блок полупрозрачным.

Переходим к следующему псевдоэлементу:
.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.

Теперь сделаем так, чтобы при наведении курсора на карточку псевдоэлементы двигались внутрь карточки. Добавим transition
для плавной анимации.
.profile-card:hover .info::before {
transform: skew(30deg) translateX(50%);
}
.profile-card:hover .info::after {
transform: skew(-30deg) translateX(40%);
opacity: 0.7;
}
Вот что получится:

Теперь делаем псевдоэлементы для самой карточки.
.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;
}

Как вы уже догадались, при наведении курсора псевдоэлементы сдвигаются внутрь. Но в этот раз траектория будет больше.
.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;
}
Получилось:

Меняем цвет текста на белый и делаем его прозрачным. Когда курсор на карточке, прозрачность убираем, чтобы текст стал видимым.
.info h2, .info p {
color: #fff;
opacity: 0;
transition: all 0.6s;
}
.profile-card:hover .info h2,
.profile-card:hover .info p {
opacity: 1;
}
Итог:

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

Курсы по программированию для получения новой специальности или повышения:
Топ бесплатных курсов и занятий: