В этом уроке я покажу вам принцип создания крутых эффектов при наведении мыши на текст. Думаю, что это будет для вас хорошей практикой в работе с JavaScript, CSS-переходами и CSS-анимацией.
В первую очередь давайте подготовим нашу разметку. Для демонстрации нам понадобиться один блок <div>
с классом .container
и вложенный параграф <p>
с классом text
, в который мы поместим рыбу текста.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Эффекты при наведении</title>
</head>
<body>
<div class="container">
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum, nisi incidunt quidem facilis ab perferendis tempore debitis pariatur! Eum et asperiores distinctio, possimus dolores nihil fugit voluptate! Qui, quibusdam impedit! Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum, nisi incidunt quidem facilis ab perferendis tempore debitis pariatur! Eum et asperiores distinctio, possimus dolores nihil fugit voluptate! Qui, quibusdam impedit! Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum, nisi incidunt quidem facilis ab perferendis tempore debitis pariatur! Eum et asperiores distinctio, possimus dolores nihil fugit voluptate! Qui, quibusdam impedit!
</p>
</div>
</body>
</html>
На этом с разметкой мы закончили, давайте перейдем к оформлению. Для этого я создам файл style.css
и подключу его в наш проект.
Базовые стили
В первую очередь для всех элементов мы изменим свойство box-sizing
на значение border-box
. А также скинем внешние отступы у элемента body
:
* {
box-sizing: border-box;
}
body {
margin: 0;
}
Стили контейнера
Для лучшей демонстрации разместим наш блок с текстом по центру экрана. Для этого мы обращаемся к классу .container
, и делаем его минимальную высоту равной высоте области просмотра. После чего меняем его тип отображения на flex
и выравниваем элементы по центру главной и поперечной оси. Также я добавлю внутренние поля слева и справа по 100px
и свойство overflow
в значении hidden
, чтобы наш текст после анимации не растягивал блок:
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 0 100px;
overflow: hidden;
}
Блок текста
Теперь перейдем к оформлению блока с классом .text
. Его содержимое мы выравняем по центру, увеличим шрифт до 25px
, а также отменим выделение текста:
.text {
text-align: center;
font-size: 25px;
user-select: none;
}
И последнее, что я хочу сделать для большего контраста, это поменять цвет текста на белый, а цвет фона на черный:
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 0 100px;
overflow: hidden;
background-color: #000;
}
.text {
text-align: center;
font-size: 45px;
user-select: none;
color: #fff;
}
На этом наше базовое оформление готово, перейдем к JavaScript. Для этого я создам файл script.js
и подключу его в самый низ тела документа, чтобы иметь из него доступ к элементам DOM-дерева.
Работа JavaScript
На самом деле наш сценарий будет очень простой. Все что нам нужно сделать, это повесить событие на каждый символ текста. Напрямую это сделать невозможно, поэтому мы обращаемся к блоку .text
. Берем его содержимое и при помощи метода replace()
, заменяем каждый не пробельный символ на элемент <span>
,
внутрь которого мы должны поместить текущий символ:
const text = document.querySelector('.text');
text.textContent.replace(/\S/g, '<span>$&</span>');
После чего записываем все это в качестве нового содержимого блока:
const text = document.querySelector('.text');
text.innerHTML = text.textContent.replace(/\S/g, '<span>$&</span>');
В итоге мы получаем тот же самый текст, но теперь каждый его символ обернут в <span>
.
Подписываемся на событие
Все что нам остается сделать, это повесить событие на каждый <span>
. Делать это напрямую мы конечно же не будем. Вместо этого мы делегируем событие на родительский блок. В нашем случае это будет событие mouseover
, которое срабатывает при наведении мыши на элемент. При желании вы можете использовать и другое событие, например, click
.
const text = document.querySelector('.text');
text.innerHTML = text.textContent.replace(/\S/g, '<span>$&</span>');
text.addEventListener('mouseover', function(e) {
});
Получать целевой элемент, на который наведен курсор, мы будем через объект события event
, а именно, через его свойство target
. Для демонстрации давайте выведем его в консоль и убедимся, что элементы находятся правильно:
const text = document.querySelector('.text');
text.innerHTML = text.textContent.replace(/\S/g, '<span>$&</span>');
text.addEventListener('mouseover', function(e) {
console.log(e.target);
});
Мы видим, что помимо самих букв, событие срабатывает и на общем блоке .text
. Чтобы это исправить, добавим дополнительную проверку. А именно, если свойство tagName
элемента не равняется SPAN
, то мы просто выходим из функции:
const text = document.querySelector('.text');
text.innerHTML = text.textContent.replace(/\S/g, '<span>$&</span>');
text.addEventListener('mouseover', function(e) {
if (e.target.tagName != 'SPAN') return;
console.log(e.target);
});
Теперь все работает как надо.
И последнее что нам осталось сделать это добавить целевому элементу какой-нибудь класс, например, active
:
const text = document.querySelector('.text');
text.innerHTML = text.textContent.replace(/\S/g, '<span>$&</span>');
text.addEventListener('mouseover', function(e) {
if (e.target.tagName != 'SPAN') return;
e.target.classList.add('active');
});
На этом наш сценарий можно считать завершенным.
Анимация символов
Вернемся к CSS
и зададим некоторые стили
для элементов <span>
.
Сейчас все они имеют строчный тип отображения.
Изменим его на inline-block
,
а также поменяем стиль курсора
на pointer
. (пойнтэ)
.text span {
display: inline-block;
cursor: pointer;
}
Эффект за счет переходов
Теперь все зависит только от нашей фантазии. Все что нам нужно сделать для создания любого эффекта - это задать свойства для элементов с классом .active
. Например, поменяем их цвет текста на красный. А также установим время перехода в 2s
, чтобы изменение было плавным:
.active {
color: red;
transition: 2s;
}
Точно также мы можем создавать и другие эффекты. Например, заменим цвет на прозрачность:
.active {
opacity: 0;
transition: 2s;
}
Теперь при наведении курсора наши буквы будут растворяться.
Эффект дыма
На этом можно было остановиться, но мы пойдем еще дальше. И зададим нашим активным элементам более сложную анимацию. Например, я хочу чтобы буквы не просто исчезали, а превращались в дым и улетали.
Для этого я добавлю им фильтр blur
в значении 20px
. А также задам трансформацию:
- смещение вправо на
300px
- смещение вверх на
300px
- вращение на
720
градусов - и увеличение масштаба в 4 раза.
.active {
opacity: 0;
filter: blur(20px);
transform: translateX(500px) translateY(-300px) rotate(720deg) scale(4);
transition: 2s;
}
По-моему это выглядит довольно круто.
Эффект за счет анимации
Для более сложной анимации, которая состоит из нескольких переходов, мы можем использовать ключевые кадры @keyframes
. Назовем их smoke
и опишем конечное состояние элементов:
@keyframes smoke {
100% {
opacity: 0;
filter: blur(20px);
transform: translateX(300px) translateY(-300px) rotate(720deg) scale(4);
}
}
Чтобы применить анимацию, используем свойство animation
:
- указываем наше название
- продолжительность в 2 секунды
- тип анимации - линейный
- и остановку на последнем кадре
.active {
animation: smoke 2s linear forwards;
}
Сейчас это выглядит точно также, как и в случае с переходом. Но при этом мы можем добавлять промежуточные состояния. Например, пусть на 20% анимации, наши элементы поменяют цвет на зеленый, а на 50% изменим его на красный:
@keyframes smoke {
20% {
color: green;
}
50% {
color: red;
}
100% {
opacity: 0;
filter: blur(20px);
transform: translateX(500px) translateY(-300px) rotate(720deg) scale(4);
}
}
Вот такая вот анимация у нас получилась. Используя этот способ, вы можете создавать и другие эффекты. Все, на что у вас хватит воображения.