Великолепный hover эффект с CSS переменными
Для того, чтобы понять, что такое CSS переменные то советую прочитать статью — Руководство по работе с переменными в CSS.
Там вы поймете, что с ними делать и как с ними быть. Ничего сложного на самом деле, только нужно немного захотеть разобраться.
А в этой статье вы узнаете как применять эти самые переменные в реальном и очень полезном кейсе. Создавая великолепный hover эффект.
Недавно я был воодушевлён забавной hover анимацией на сайте Grover. Двигая мышкой над кнопкой подписки появляется цветной градиент, который следует за курсором во время его движения. Идея простая, но как результат мы получаем кнопку, которая выделяется на фоне других и прямо напрашивается на то, чтобы по ней кликнули.
Как мы можем достигнуть такого же эффекта, чтобы наш сайт тоже выделялся? Ну, это не так сложно, как вы уже могли подумать.
Отслеживание позиции
Первое, что нам нужно это позиция мышки.
document.querySelector('.button').onmousemove = (e) => {
const x = e.pageX - e.target.offsetLeft
const y = e.pageY - e.target.offsetTop
e.target.style.setProperty('--x', `${ x }px`)
e.target.style.setProperty('--y', `${ y }px`)
}
Выберите элемент и ждите пока пользователь не двинет мышкой вдоль него.
Высчитайте позицию относительно элемента.
Сохраните координаты в CSS переменную.
Да, всего 9 строчек кода, чтобы указать CSS где пользователь позиционирует мышку. Вообще количество эффектов, которое вы можете сделать с помощью этой информации просто бесчисленно. Но давайте завершим наш CSS, для начала.
Анимируем градиент
Теперь у нас есть координаты записанные в CSS переменные и мы можем использовать их по всему нашему CSS.
.button {
position: relative;
appearance: none;
background: #f72359;
padding: 1em 2em;
border: none;
color: white;
font-size: 1.2em;
cursor: pointer;
outline: none;
overflow: hidden;
border-radius: 100px;
span {
position: relative;
}
&::before {
--size: 0;
content: '';
position: absolute;
left: var(--x);
top: var(--y);
width: var(--size);
height: var(--size);
background: radial-gradient(circle closest-side, #4405f7, transparent);
transform: translate(-50%, -50%);
transition: width .2s ease, height .2s ease;
}
&:hover::before {
--size: 400px;
}
}
Оберните текст в span
, чтобы избежать того, что градиент появится над ним.
Начните с width
и height
0px
и поднимайте до 400px
, когда пользователь наведет на кнопку. И не забудьте выставить переход (transition
), чтобы бы все это происходило плавно, быстро и красиво.
Используйте координаты, чтобы следовать за мышкой.
Примените radial-gradient
для background
и используйте closest-side circle. Closest-side заполнит весь before, не выходя за него.
Результат
И всё! Добавьте недостающий HTML и наслаждайтесь кнопкой.
<button class="button">
<span>Hover me I'm awesome</span>
</button>
Огромные возможности
Вы можете сделать огромное количество эффектов, реагируя на позицию мышки. Это прекрасно и с этим забавно поиграться.
Вот схожая анимация, которую я использовал:
May the hover be with you pic.twitter.com/2jrmVorLRW
— Tobias Reich (@electerious) January 28, 2018
Или включите фантазию и сделайте 3D параллакс кнопку:
3D parallax button with JS controlled CSS variables @CodePen 🎉 https://t.co/qE0woiNip8 pic.twitter.com/Wyi0xjRzPq
— Tobias Reich (@electerious) October 21, 2016
Возможности безграничным. Только попробуйте сами.
Вопросы и ответы
Почему анимация width
и height
вместо использования transform: scale()
?
Производительность довольно плоха при анимации width и height, и вам надо всегда стараться использовать transform при доступной возможности. Так почему я так не делал? Проблема в том, что браузер рендерит элементы (которые трансформируются) в ускоренном слое. Этот слой может вызывать проблемы в случае, когда кнопка имеет не прямоугольные края.
Конечно же есть способы для применения transform, но некоторые браузеры этого не любят. Отказ от применения transition до transform это одно потенциальное решение. Есть также обходное решение для Safari, которое может исправить эту проблему с обрезкой.