Hover CSS эффекты для блока и ссылок с примерами кода
Hover CSS эффекты для блока задаются псевдоклассом :hover: он меняет стиль элемента, пока указатель находится над ним. CSS при наведении позволяет менять цвет ссылки, поднимать карточку и раскрывать подменю. Соберите плавные эффекты по примерам кода и учтите клавиатуру, сенсорные экраны и производительность.
Что такое :hover в CSS
Псевдокласс :hover выбирает элемент под указателем. Браузер применяет правило, пока состояние сохраняется.
Селектор ставит двоеточие перед названием состояния. Запись .card:hover выбирает элемент с классом card, когда курсор находится над карточкой.
.card {
color: #fff;
background-color: #40577d;
}
.card:hover {
background-color: #9a4771;
}CSS меняет оформление без JavaScript и не переписывает HTML. Элемент должен существовать в документе, а селектор должен его выбрать.
Для ссылок сохраняйте порядок LVHA: :link → :visited → :hover → :active. При одинаковой специфичности более позднее правило получает приоритет.
a:link {
color: #2457a6;
}
a:visited {
color: #7040a0;
}
a:hover {
color: #d04444;
}
a:active {
color: #111;
}Состояние :active идет после :hover, поэтому нажатая ссылка может получить цвет правила :active. Синтаксис описан в справке MDN о :hover.
Hover для ссылок и подчеркивания
Селектор a:hover задает оформление ссылки при наведении. Чтобы изменить ее цвет в CSS, задайте базовое правило и правило состояния.
<a class="link" href="/catalog.html">Открыть каталог</a>.link {
color: #2457a6;
text-decoration: underline;
text-underline-offset: 0.2em;
}
.link:hover,
.link:focus-visible {
color: #c43d3d;
text-decoration-thickness: 0.14em;
}text-underline-offset отодвигает линию от букв. :focus-visible повторяет сигнал для пользователя, который перемещается клавишей Tab.
Плавное подчеркивание при наведении в CSS можно создать фоновой полосой. В исходном состоянии ширина фона равна нулю.
.link--line {
color: #2457a6;
text-decoration: none;
background: linear-gradient(#f0c928, #f0c928) 0 100% / 0 0.25em no-repeat;
transition: background-size 180ms ease;
}
.link--line:hover,
.link--line:focus-visible {
background-size: 100% 0.25em;
}Полоса вырастает до ширины текста и плавно возвращается к нулю после ухода курсора.
Волнистую линию можно нарисовать статичным SVG внутри background-image. Такой вариант не требует отдельной картинки.
.wave-link {
color: #2457a6;
text-decoration: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 6'%3E%3Cpath d='M0 3 Q5 0 10 3 T20 3 T30 3 T40 3' fill='none' stroke='%23d04444' stroke-width='2'/%3E%3C/svg%3E");
background-position: 0 100%;
background-repeat: repeat-x;
background-size: 40px 6px;
}
.wave-link:hover,
.wave-link:focus-visible {
background-size: 28px 6px;
}При наведении волна станет плотнее под текстом. Если фон снижает читаемость, оставьте обычное подчеркивание.
Плавный переход через transition
transition описывает переход между двумя значениями свойства. В записи участвуют свойство, длительность, функция времени и задержка.
.button {
transition-property: color, background-color, transform;
transition-duration: 180ms;
transition-timing-function: ease-out;
transition-delay: 0ms;
}Краткая запись объединяет параметры: transition: color 180ms ease-out 0ms. Длительность задавайте в миллисекундах или секундах.
Пишите transition в базовом состоянии. Тогда браузер анимирует включение эффекта и возврат после ухода указателя.
.card {
transition: transform 180ms ease, box-shadow 180ms ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 24px rgb(0 0 0 / 18%);
}Карточка поднимется на 4 пикселя и получит тень. После ухода курсора она плавно вернется.
Не ставьте transition: all без причины. Такое правило затронет каждое изменившееся свойство и способно анимировать размеры, отступы и другие параметры.
Полный синтаксис разобран в документации MDN о transition.
Hover css эффекты для блока
Hover css эффекты для блока меняют масштаб, положение и оформление. Общий класс задает базовый вид, а каждый рецепт меняет одно свойство.
<article class="demo-card">
<a class="demo-card__link" href="/catalog.html">Открыть каталог</a>
</article>.demo-card {
width: 220px;
min-height: 120px;
padding: 24px;
color: #fff;
background-color: #40577d;
border-radius: 12px;
transition: transform 180ms ease, opacity 180ms ease,
box-shadow 180ms ease, border-radius 180ms ease,
background-color 180ms ease;
}
.demo-card__link {
color: inherit;
}
.demo-card__link:focus-visible {
outline: 2px solid currentColor;
outline-offset: 4px;
}Масштаб увеличивает отрисовку блока, но не меняет его width и height. Соседи сохраняют прежние места.
.demo-card:hover,
.demo-card:focus-within {
transform: scale(1.06);
}Карточка станет крупнее при наведении или фокусе ссылки внутри.
.demo-card:hover,
.demo-card:focus-within {
transform: rotate(-3deg);
}Блок повернется на 3 градуса против часовой стрелки.
.demo-card:hover,
.demo-card:focus-within {
transform: translateY(-8px);
}Верхний край поднимется на 8 пикселей без изменения места в потоке.
.demo-card:hover,
.demo-card:focus-within {
opacity: 0.65;
box-shadow: 0 12px 28px rgb(0 0 0 / 22%);
border-radius: 28px;
background-color: #9a4771;
}Блок станет прозрачнее, получит тень, более круглые углы и новый фон. Проверьте контраст текста после смены цвета.
CSS hover на другой элемент
Чтобы при наведении изменить другой элемент, используйте комбинаторы селекторов. Наведенный элемент и цель должны быть связаны соседством или общей вложенностью.
Комбинатор + выбирает только следующего соседа. Цель должна идти сразу после триггера.
<button class="trigger" type="button">Навести</button>
<span class="target">Текст изменится</span>.trigger:hover + .target,
.trigger:focus-visible + .target {
color: #d04444;
}Текст справа изменит цвет при наведении или клавиатурном фокусе.
Комбинатор ~ выбирает всех подходящих соседей после триггера.
.trigger:hover ~ .target,
.trigger:focus-visible ~ .target {
color: #d04444;
}Цвет изменится у каждого последующего элемента с классом target.
Пробел между селекторами выбирает потомка. Запись .card:hover .title работает, если заголовок находится внутри карточки.
.card:hover .title {
color: #f0c928;
}
.card:hover .icon {
transform: translateY(-3px);
}Заголовок пожелтеет, а значок поднимется на 3 пикселя.
Псевдокласс :has() выбирает карточку, внутри которой находится наведенная кнопка.
.card:has(.button:hover),
.card:has(.button:focus-visible) {
outline: 2px solid #f0c928;
}Контур появится вокруг карточки при наведении на кнопку или ее фокусе.
Тот же прием меняет предыдущий элемент внутри общего родителя.
.row:has(.status:hover) .label,
.row:has(.status:focus-visible) .label {
color: #d04444;
}Подпись перед кнопкой изменит цвет. Селектор не достает произвольный несвязанный узел: цель должна быть потомком, соседом или частью общего родителя.
Для окружений без :has() оставьте базовый стиль и продублируйте действие на общем контейнере. Если изменить разметку нельзя, используйте JavaScript для переключения класса на родителе.
Синтаксис :has() описан в справке MDN. Такое правило стоит применять после проверки целевых браузеров и с нейтральным оформлением по умолчанию.
Выпадающее меню при наведении
Родительский пункт списка удерживает подменю под курсором. Состояние :focus-within открывает тот же блок при переходе клавишей Tab.
<nav class="menu" aria-label="Основное меню">
<ul class="menu__list">
<li class="menu__item">
<a href="/catalog.html">Каталог</a>
<ul class="menu__submenu">
<li><a href="/books.html">Книги</a></li>
<li><a href="/courses.html">Курсы</a></li>
</ul>
</li>
</ul>
</nav>.menu__list,
.menu__submenu {
margin: 0;
padding: 0;
list-style: none;
}
.menu__item {
position: relative;
}
.menu__submenu {
position: absolute;
top: 100%;
left: 0;
min-width: 180px;
opacity: 0;
visibility: hidden;
transform: translateY(6px);
transition: opacity 160ms ease, transform 160ms ease,
visibility 0s linear 180ms;
}
.menu__item:hover .menu__submenu,
.menu__item:focus-within .menu__submenu {
opacity: 1;
visibility: visible;
transform: translateY(0);
transition-delay: 0s;
}При закрытии visibility сохраняет подменю еще 180 миллисекунд. Курсор успевает перейти к дочерним ссылкам.
Нажмите Tab до ссылки «Каталог», затем перейдите к «Книгам» и «Курсам». Подменю останется открытым, пока фокус находится внутри пункта.
Hover на телефонах и для клавиатуры
Тач-устройство не дает такого же постоянного указателя, как мышь. При этом браузер может имитировать или сохранять состояние :hover после касания, поэтому эффект иногда выглядит «залипающим».
Ограничьте декоративные правила медиазапросом для точного указателя, который умеет наводиться.
@media (hover: hover) and (pointer: fine) {
.card:hover {
transform: translateY(-4px);
}
.link:hover {
color: #c43d3d;
}
}Клавиатурные состояния оставляйте вне этого блока. Так ссылка сохраняет обратную связь без мыши.
.card:focus-within {
outline: 2px solid #f0c928;
outline-offset: 4px;
}
.card__link:focus-visible {
outline: 3px solid #2457a6;
outline-offset: 4px;
}Если сенсорный экран не поддерживает нужное поведение, не прячьте важное действие только в :hover. Для меню можно оставить подменю раскрытым или добавить отдельную кнопку.
@media (hover: none) {
.menu__submenu {
position: static;
opacity: 1;
visibility: visible;
transform: none;
transition: none;
}
}Ссылки подменю появятся сразу под пунктом «Каталог». Медиазапрос (hover: none) не заменяет проверку реального сценария на телефоне.
Уважайте настройку уменьшения движения пользователя.
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
transition-duration: 0.01ms;
animation-duration: 0.01ms;
animation-iteration-count: 1;
scroll-behavior: auto;
}
}Цвет, контраст и видимый фокус сохраняются, а длительные переходы почти исчезают. Справка о фокусе находится в документации MDN о :focus-visible.
Производительность hover-анимаций
Для плавности выбирайте свойства, которые не меняют геометрию документа. Обычно подходят transform и opacity.
.tile {
transition: transform 180ms ease, opacity 180ms ease;
}
.tile:hover {
transform: translateY(-6px) scale(1.02);
opacity: 0.92;
}Блок поднимется, немного увеличится и сохранит прежнее место в раскладке.
Изменение width, height, top или margin может запустить перерасчет раскладки. В сетке карточек такой эффект сдвигает соседей.
Фон, тень и скругление способны вызвать перерисовку. Свойство will-change применяйте точечно, когда элемент готовится к сложной анимации.
.hero-card {
will-change: transform;
}
.hero-card:hover {
transform: scale(1.04);
}Не добавляйте will-change всем карточкам. Браузер потратит лишние ресурсы на подготовку множества элементов.
В DevTools откройте панель Rendering, включите Paint flashing и наведите курсор на элемент. Зеленая подсветка покажет области, которые браузер перерисовывает.
Описание режима находится в документации Chrome DevTools о Rendering.
Ошибки при работе с :hover
Нарушенный порядок LVHA создает неожиданный цвет ссылки. При одинаковой специфичности оставляйте состояния в порядке :link, :visited, :hover, :active.
Переход только в :hover исчезает рывком после ухода курсора. Перенесите transition в базовый селектор.
Изменение размера или добавление границы сдвигает соседей. Оставьте место под границу заранее.
.button {
border: 2px solid transparent;
}
.button:hover,
.button:focus-visible {
border-color: #f0c928;
}Цвет границы изменится без роста внешнего размера кнопки.
Меню закрывается по пути к подменю, когда между ними остается просвет. Общий родитель, абсолютное позиционирование и задержка visibility сохраняют область меню.
Эффект только для мыши недоступен пользователям клавиатуры. Добавляйте важное состояние к :focus-visible, а вложенное меню открывайте через :focus-within.
Слишком сильный масштаб отвлекает от содержимого. Ограничьте движение и учтите prefers-reduced-motion: reduce.
Популярное за неделю
- Как создать сайт самому в 2026: 4 способа + пошаговая инструкция 34 мин чтения
- Лучшие конструкторы для создания сайтов — плюсы, минусы и сравнения 22 мин чтения
- overflow hidden что это и почему обрезка не работает 6 мин чтения
- 50 примеров CSS3‑кнопок с эффектами для сайта 5 мин чтения
- 17 эффектных CSS‑анимаций с готовыми примерами 3 мин чтения
- 19 CSS‑спиннеров и прелоадеров для загрузки 5 мин чтения
Комментарии