Анимация при наведении: практика с transition и :hover

В этом уроке соберём живую кнопку на чистом CSS: :hover и :focus меняют её вид, а transition делает изменение плавным. По шагам разберём разметку, какое состояние должно появляться при наведении и клавиатурном фокусе, и в какое именно место CSS-правил положить transition, чтобы анимация одинаково плавно работала в обе стороны - и при появлении эффекта, и при его исчезновении.

Попробуй прямо сейчас: наведи курсор на кнопку - она поднимается и меняет цвет, а при уходе курсора так же плавно возвращается на место. Кликни рядом и переключайся между кнопкой и остальной страницей клавишей Tab - при получении фокуса клавиатурой кнопка реагирует точно так же. Перенеси строку transition внутрь блока .btn:hover - и наведение останется плавным, а вот возврат при уходе курсора станет мгновенным, без анимации.

Шаг 1: разметка и стартовые стили кнопки

Для кликабельной кнопки нужен настоящий тег button, а не div с обработчиком клика. У button из коробки есть то, что иначе пришлось бы дописывать вручную: элемент попадает в очередь переключения по Tab, реагирует на Enter и пробел как на клик, и скринридеры сами объявляют его как кнопку. Стартовые стили (padding, border-radius, цвет фона) задаются на этом же базовом селекторе - именно они будут меняться при наведении и фокусе.

<button class="btn">Нажми меня</button> - настоящая кнопка: фокусируется по Tab, кликабельна с клавиатуры без единой строчки JS.

Неправильное ожидание - что div с курсором pointer выглядит и ведёт себя как кнопка:

<div class="btn" onclick="...">Нажми меня</div> - визуально похоже, но div не попадает в очередь Tab и не реагирует на Enter/пробел без дополнительных tabindex и обработчиков клавиатуры - лишняя работа ради того, что button даёт бесплатно.

Шаг 2: что меняется при наведении - :hover, :focus и transform

Целевое состояние кнопки описывается в правиле .btn:hover, .btn:focus - именно через запятую, оба селектора сразу. :hover срабатывает при наведении мышью, а :focus - когда элемент получает фокус любым способом, включая клавишу Tab. Если указать только :hover, пользователи, которые работают с клавиатуры (а не только те, кто использует специальные технологии), просто не увидят никакой реакции кнопки на фокус - визуально она ничем не будет выделяться среди остальной страницы.

.btn:hover, .btn:focus { background: tomato; transform: translateY(-4px); } - одинаковый эффект и для мыши, и для клавиатуры: оба способа взаимодействия получают одинаковый визуальный отклик.

Неправильное ожидание - что :hover сам по себе покрывает всех пользователей:

.btn:hover { background: tomato; transform: translateY(-4px); } - при переключении на кнопку клавишей Tab не произойдёт вообще ничего: не сработает ни :hover (курсора мыши на кнопке нет), ни визуальный отклик для фокуса, потому что :focus не описан.

Шаг 3: делаем переход плавным - куда положить transition

Место, где написан transition, решает, будет ли анимация работать в обе стороны. Если положить transition на базовый селектор .btn (тот, что действует и без наведения, и при наведении), переход плавно сыграет и при появлении эффекта, и при его исчезновении. Если же написать transition только внутри .btn:hover, .btn:focus - наведение действительно будет плавным, а вот при уходе курсора или потере фокуса кнопка мгновенно, без анимации, вернётся в исходное состояние: у базового правила .btn transition вообще не указан, а значит его длительность по умолчанию равна 0s, и переход назад происходит мгновенно.

.btn { transform: translateY(0); transition: transform .3s ease-out, background-color .3s; } .btn:hover, .btn:focus { background: tomato; transform: translateY(-4px); } - transition на базовом селекторе: анимация плавно играет и вперёд, и назад.

Неправильное ожидание - что можно положить transition прямо туда же, где описано целевое состояние:

.btn:hover, .btn:focus { background: tomato; transform: translateY(-4px); transition: transform .3s ease-out, background-color .3s; } - наведение сыграет плавно, но уход курсора вернёт кнопку в исходное положение мгновенным скачком, без единой миллисекунды анимации.

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

ОшибкаЧто происходитКак исправить
Сделать кнопку из div с onclick вместо button Элемент не попадает в очередь Tab и не реагирует на Enter/пробел - кнопка недоступна с клавиатуры Использовать настоящий тег button - фокус и реакция на клавиатуру работают из коробки
Описать эффект только для :hover, забыв про :focus Пользователи, переключающиеся по Tab, не получают вообще никакого визуального отклика на кнопке Всегда описывать состояние взаимодействия как .btn:hover, .btn:focus вместе
Положить transition внутрь .btn:hover, а не на базовый .btn Наведение анимируется плавно, а возврат при уходе курсора происходит мгновенным скачком без анимации Всегда указывать transition на базовом селекторе - том, что действует и без наведения тоже
Указать в transition только одно из нескольких меняющихся свойств (например, только transform) Свойства, не перечисленные в transition, меняются мгновенно, пока transform - плавно; эффект выглядит дёргано Перечислять через запятую все свойства, которые меняются в целевом состоянии

Шпаргалка

ШагЧто сделать
РазметкаНастоящий <button class="btn">...</button>, а не div с обработчиком клика
Стартовые стилиНа базовом .btn - именно они изменятся при взаимодействии
Целевое состояние.btn:hover, .btn:focus вместе - одинаковый отклик для мыши и клавиатуры
Где писать transitionНа базовом .btn, не внутри :hover/:focus - иначе анимация не сыграет в обратную сторону
Что перечислить в transitionЧерез запятую все свойства, которые реально меняются (transform, background-color, box-shadow...)
Функция плавностиease-out хорошо подходит для эффекта "кнопка поднимается навстречу" - быстрый старт, мягкое торможение

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

Через что лучше делать анимацию при наведении - transition или @keyframes?

Для простого эффекта из двух состояний (обычное и при наведении), который должен плавно возвращаться назад при уходе курсора, лучше подходит transition - он "из коробки" анимирует и вперёд, и назад. @keyframes стоит приберечь для более сложных, цикличных или однонаправленных анимаций с несколькими промежуточными шагами, которые не обязаны плавно откатываться назад сами по себе.

Почему при уходе курсора с кнопки анимация иногда не проигрывается, а элемент просто дёргается обратно?

Почти всегда причина в том, что transition написан внутри правила :hover (или :focus), а не на базовом селекторе. Когда состояние наведения исчезает, снова начинает действовать базовое правило - а если в нём самом transition не указан, переход происходит мгновенно, без анимации. Решение - переносить transition на базовый селектор элемента.

Категория
Поделиться в социальных сетях

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

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

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

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

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