Анимированные кнопки и ссылки: практика

Кнопки и ссылки - самое частое место применения CSS-анимаций на сайте. Для кнопок обычно комбинируют background-color, transform (scale или сдвиг вверх) и box-shadow. Для ссылок эффектнее всего смотрится анимированное подчёркивание - но собрать его нужно правильным способом, иначе оно сломается на ссылке, которая переносится на несколько строк.

Попробуй прямо сейчас: наведи на кнопку - она чуть поднимается вверх, слегка увеличивается и получает тень, всё это за счёт transform и box-shadow в паре с transition на базовом селекторе .btn (а не только внутри :hover). Наведи на ссылку - под ней слева направо "вырастает" линия: это не ::after, а анимация background-size у обычного background-image - ниже разберём, почему для ссылки это надёжнее.

Кнопки: комбо из фона, тени и scale

В hover-эффектах кнопок почти всегда комбинируют три свойства: background-color (смена цвета фона), transform - чаще всего scale() для лёгкого увеличения или translateY() для "приподнимания" вверх (обе техники разбирали в уроке про scale), и box-shadow, которая усиливает ощущение, что кнопка физически приподнялась над страницей. Ничего технически нового здесь нет - весь набор уже пройден в курсе, важна именно комбинация и правильное место transition.

Как и в уроке про transition при hover, transition обязательно пишется на БАЗОВОМ селекторе .btn, а не внутри .btn:hover - иначе плавным будет только "включение" эффекта при наведении, а "выключение" при уходе курсора произойдёт мгновенным скачком.

.btn { transition: background-color .3s, transform .2s, box-shadow .3s; } .btn:hover { background: #4338ca; transform: translateY(-3px) scale(1.03); box-shadow: 0 10px 20px rgba(79, 70, 229, .35); } - transition на базовом классе, разные свойства могут анимироваться с разной длительностью.

.btn:hover { background: #4338ca; transform: translateY(-3px) scale(1.03); box-shadow: 0 10px 20px rgba(79, 70, 229, .35); transition: background-color .3s, transform .2s, box-shadow .3s; } - transition написан только внутри :hover: при наведении эффект НЕ будет плавным (переход появляется только когда правило уже применилось), а при уходе курсора кнопка мгновенно вернётся в исходное состояние.

Ссылки: анимированное подчёркивание без сюрпризов на переносе строк

Самый очевидный способ анимировать подчёркивание ссылки - псевдоэлемент ::after с position: absolute и анимацией width или transform: scaleX(). Но у него есть скрытая проблема: если ссылка достаточно длинная и переносится на несколько строк, ::after - это ОДИН блок, привязанный к элементу целиком, а не к каждой строке отдельно, поэтому линия появляется только под последней строкой текста, а остальные строки остаются без подчёркивания вообще.

Надёжнее использовать не псевдоэлемент, а сам background элемента: линию рисует background-image: linear-gradient(currentColor, currentColor) - фактически сплошная полоса цвета текста, - а её ширину анимирует transition по background-size, растущему от 0% до 100%. Такой фон браузер рисует персонально для каждого строчного фрагмента ссылки, поэтому линия появляется под КАЖДОЙ строкой, даже если их несколько.

.link { position: relative; } .link::after { content: ""; position: absolute; left: 0; bottom: -2px; width: 100%; height: 2px; background: currentColor; } - на многострочной ссылке линия окажется только под последней строкой.

.link { text-decoration: none; background-image: linear-gradient(currentColor, currentColor); background-position: 0% 100%; background-repeat: no-repeat; background-size: 0% 2px; transition: background-size .3s; } .link:hover { background-size: 100% 2px; } - линия появляется под каждой строкой ссылки, даже если она переносится.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Писать transition только внутри :hover, а не на базовом селекторе Наведение резкое или "включается" рывком, возврат в исходное состояние - мгновенный Переносить transition на базовый селектор, как в уроке про transition при hover
Анимировать подчёркивание ссылки через ::after на потенциально многострочном тексте Линия появляется только под последней строкой, остальные строки остаются без неё Использовать background-image + background-size вместо ::after
Не оборачивать hover-эффекты в @media (any-hover: hover) там, где сайт открывают и с телефона На тачскрине эффект "залипает" после тапа до следующего касания в другом месте Оборачивать критичные hover-стили в @media (any-hover: hover), чтобы они срабатывали только там, где есть настоящее наведение
Совмещать сразу много transform-эффектов на кнопке (scale + translateY + rotate) без проверки Кнопка "дёргается" или прыгает не туда, тяжело предсказать итоговое положение Добавлять transform-функции по одной и проверять результат на каждом шаге

Шпаргалка

ЗаписьЧто означает
transition на .btn (не на .btn:hover)Плавными будут и наведение, и уход курсора
transform: translateY(-3px) scale(1.03);Кнопка приподнимается и слегка увеличивается
::after + position:absolute для подчёркиванияЛомается на многострочной ссылке - линия только под последней строкой
background-image: linear-gradient(currentColor, currentColor) + background-sizeНадёжный способ подчёркивания - работает на любом числе строк
@media (any-hover: hover) { ... }Hover-стили сработают только там, где есть настоящее наведение (мышь/трекпад)

Коротко: отвечаем на вопросы

Почему на телефоне hover-эффект кнопки "залипает" после того, как убрал палец?

У сенсорного экрана физически нет состояния наведения - когда пользователь тапает по кнопке, браузер условно "включает" :hover и держит его до следующего касания в другом месте, а не отпускает сразу, как это делает мышь при уходе курсора. Современное решение - оборачивать hover-стили в @media (any-hover: hover) { ... }: это условие истинно только на устройствах, у которых есть настоящее наведение (мышь, трекпад), и ложно на чистом тачскрине, поэтому там залипать будет нечему.

Можно ли анимировать подчёркивание ссылки через ::after, если текст точно в одну строку?

Да, для однострочной ссылки способ через ::after работает без проблем - искажение проявляется только когда текст переносится на несколько строк. Но если заранее неизвестно, поместится ли ссылка в одну строку на всех экранах (а на мобильном экране длинная ссылка почти всегда перенесётся), надёжнее сразу использовать background-image + background-size - он работает одинаково в обоих случаях.

Категория
Поделиться в социальных сетях
1. Переходы: transition
2. Трансформации: transform
3. Ключевые кадры и animation
4. Фильтры: filter
5. Практика: живые интерфейсы
6. Производительность и доступность

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×