Содержание
Keyframes создают анимации, которые играют сами по себе. Transition — это другой инструмент. Он делает плавными переходы между состояниями, которые вызываются конкретным событием: наведением курсора, получением фокуса, добавлением класса через JavaScript. Если keyframes — режиссёр, который запускает сцену по своему расписанию, то transition скорее актёр, который реагирует на зрителя.
transition vs @keyframes
Прежде чем разбирать синтаксис, стоит зафиксировать границу между двумя инструментами.
@keyframes задаёт анимацию, которая проигрывается автоматически. Она может быть бесконечной, многокадровой, с промежуточными точками. Элемент двигается, пульсирует, вращается — без участия зрителя.
transition задаёт плавный переход между двумя состояниями. Он срабатывает только при изменении свойства — через :hover, :focus, :active или через JavaScript. Нет изменения — нет перехода. Transition всегда работает между двумя точками, без промежуточных кадров.
Проще говоря: нужна постоянная анимация — используйте keyframes. Нужна реакция на действие зрителя — используйте transition.
Анатомия transition
Transition пишется на базовом состоянии элемента (не на :hover). Это самая частая ошибка начинающих, поэтому сразу покажем разницу.
<div class="no-transition"></div>
<div class="with-transition"></div>
.no-transition:hover {
background: #9EFF70;
transform: scale(1.2);
}
/* Без transition — мгновенный скачок */
.with-transition {
transition: background 0.3s ease,
transform 0.3s ease;
}
.with-transition:hover {
background: #9EFF70;
transform: scale(1.2);
}
/* С transition — плавный переход.
transition пишется на БАЗОВОМ состоянии,
а не на :hover. */
Левый квадрат меняет цвет и масштаб мгновенно — скачком. Правый делает то же самое, но плавно. Разница — одна строка: transition: background 0.3s ease, transform 0.3s ease.
Свойство transition принимает четыре значения через пробел: какое свойство анимировать, за какое время, с какой timing-функцией и с какой задержкой. Последнее — опционально.
<div class="fast">0.15s</div>
<div class="medium">0.4s</div>
<div class="slow">1s</div>
<div class="delay">0.3s + delay</div>
.fast { transition: transform 0.15s ease; }
.medium { transition: transform 0.4s ease; }
.slow { transition: transform 1s ease; }
/* transition: свойство duration timing delay */
.delay { transition: transform 0.3s ease 0.5s; }
/* 0.5s delay — переход начнётся через
полсекунды после наведения.
Полезно для вложенных элементов:
сначала карточка, потом текст внутри. */
Четыре квадрата с разной скоростью. 0.15 секунды — мгновенная реакция, подходит для мелких элементов вроде иконок и кнопок. 0.4 секунды — комфортный темп для большинства hover-эффектов. 1 секунда — замедленное, созерцательное движение. Четвёртый квадрат показывает transition-delay: 0.5s — переход начинается через полсекунды после наведения.
Оптимальная длительность transition для hover-эффектов с 0.2–0.4 секунды. Короче и зритель не успеет заметить переход. Длиннее и интерфейс начнёт казаться вялым. Для крупных элементов можно увеличить до 0.5–0.6 секунд.
Галерея hover-эффектов
Вот восемь приёмов, которые вы можете использовать в веб-плакате. Все реализованы через transition — наведите курсор на каждый блок.
<div class="h-scale">scale</div>
<div class="h-rotate">rotate</div>
<div class="h-color">color</div>
<div class="h-opacity">opacity</div>
<div class="h-shadow">shadow + lift</div>
<div class="h-radius">radius</div>
<div class="h-width">scaleX</div>
<div class="h-multi">всё сразу</div>
.h-scale:hover { transform: scale(1.08); }
.h-rotate:hover { transform: rotate(12deg); }
.h-color:hover { background: black; color: white; }
.h-opacity:hover { opacity: 0.4; }
.h-shadow:hover {
box-shadow: 0 8px 24px rgba(254,57,4,0.4);
transform: translateY(-4px);
}
.h-radius:hover { border-radius: 50%; }
.h-width:hover { transform: scaleX(1.15); }
.h-multi:hover {
background: #FE3904;
transform: scale(1.1) rotate(5deg);
border-radius: 50%;
}
scale — элемент увеличивается. Самый частый hover-эффект. Подходит для карточек, кнопок, интерактивных зон.
rotate — поворот. Здесь с cubic-bezier для упругости: элемент проворачивается чуть дальше и пружинит обратно.
color — смена фона и цвета текста. Подходит для текстовых блоков и ссылок.
opacity — затухание. Элемент становится полупрозрачным, намекая «здесь можно нажать».
shadow + lift — тень и подъём вверх через translateY(-4px). Создаёт ощущение, что элемент приподнялся над страницей. Классика карточного дизайна.
radius — скругление углов. Квадрат превращается в круг. Простой, но визуально яркий эффект.
scaleX — растягивание по горизонтали. Подходит для кнопок и навигационных элементов.
всё сразу — цвет, масштаб, поворот и скругление одновременно. Показывает, что transition без проблем обрабатывает несколько свойств параллельно.
Несколько transition
Когда нужно анимировать несколько свойств, каждое перечисляется через запятую. Это позволяет задать разную длительность и timing-функцию для каждого свойства.
Карточка
Наведите, чтобы увидеть четыре transition одновременно
<div class="card">
<h3>Карточка</h3>
<p>Наведите...</p>
</div>
.card {
transition:
background 0.3s ease,
border-color 0.3s ease,
transform 0.3s ease,
box-shadow 0.4s ease;
}
.card:hover {
background: #2a2a2a;
border-color: #FE3904;
transform: translateY(-8px);
box-shadow: 0 12px 32px rgba(254,57,4,0.2);
}
.card:hover h3 {
color: #FE3904;
}
/* Каждое свойство — своя строка
в transition. Можно задать разную
duration: shadow медленнее (0.4s),
остальные быстрее (0.3s). */
Карточка при наведении меняет фон, цвет рамки, положение (поднимается на 8px) и тень. Четыре transition работают одновременно. Обратите внимание, что shadow длится 0.4 секунды, а остальные — 0.3. Тень чуть запаздывает и догоняет, создавая каскадное ощущение.
Заголовок внутри карточки тоже меняет цвет. Его transition написан на самом элементе h3, а hover — на родителе .card:hover h3. Это паттерн «hover на родителе, эффект на ребёнке».
transition: all
Вместо перечисления конкретных свойств можно написать transition: all 0.3s ease. Это применит одинаковый переход ко всем изменяемым свойствам. Удобно для прототипирования, но у подхода есть минус: все свойства будут двигаться с одинаковым timing и duration.
<div class="box-all">...</div>
<div class="box-specific">...</div>
/* all — удобно, но грубо */
.box-all {
transition: all 0.3s ease;
}
/* Конкретные свойства — контроль */
.box-specific {
transition:
transform 0.3s cubic-bezier(0.34,1.56,0.64,1),
background 0.5s ease;
}
/* С all все свойства переходят одинаково.
С конкретными — у каждого свой характер.
transform пружинит (bounce),
background плавно меняется (ease). */
Левый блок использует transition: all 0.3s ease — все изменения происходят одинаково. Правый перечисляет свойства по отдельности: transform получает упругую кривую cubic-bezier (пружинит), а background — плавный ease длительностью 0.5 секунды. Результат ощутимо живее, потому что у каждого свойства свой характер.
transition: all может вызвать нежелательные побочные эффекты. Если где-то в CSS случайно изменится padding или width при hover, all подхватит и это. Для финальной версии плаката лучше перечислять конкретные свойства. Для экспериментов и прототипов — all вполне допустим.
Ограничения transition
Transition умеет многое, но не всё.
<div class="limit-ok">...</div>
<div class="limit-display">...</div>
<div class="limit-height">...</div>
/* ✓ transform и opacity — лучший выбор */
.limit-ok {
transition: transform 0.3s, opacity 0.3s;
}
/* ✗ display: none → block нельзя.
Обходной путь: opacity 1 → 0 */
.limit-display {
transition: opacity 0.3s ease;
}
.limit-display:hover { opacity: 0; }
/* ⚠ height: auto → px — не работает.
Нужно указать конкретные числа */
.limit-height {
height: 90px;
transition: height 0.4s ease;
}
.limit-height:hover { height: 140px; }
display: none → block — transition не может сделать этот переход плавным. Элемент просто появляется мгновенно. Обходной путь: вместо скрытия через display используйте opacity: 0 с pointer-events: none, и анимируйте opacity.
height: auto — transition не умеет интерполировать между auto и конкретным значением. Если вам нужно развернуть блок с неизвестной высотой, задайте max-height с запасом (например, max-height: 0 → max-height: 500px) и анимируйте его.
Transition всегда двусторонний. Когда вы убираете курсор, переход происходит в обратную сторону с тем же duration. Если нужно, чтобы появление было быстрым, а исчезновение медленным, можно задать разные transition для базового состояния и для hover.
Наконец, transition не поддерживает промежуточные кадры. Если нужна анимация с тремя и более состояниями, используйте @keyframes. Transition — это всегда точка A и точка B.
Hover на родителе
Часто нужно, чтобы при наведении на контейнер менялись несколько элементов внутри него. Для этого hover вешается на родителя, а transition — на каждый дочерний элемент.
<div class="card">
<div class="card-image"></div>
<div class="card-body">
<div class="card-title">Название</div>
<div class="card-desc">Описание...</div>
<div class="card-arrow">→</div>
</div>
</div>
.card-image {
transition: transform 0.4s ease;
}
.card-title {
transition: color 0.3s ease;
}
.card-arrow {
transition: transform 0.3s ease;
}
/* Hover на родителе — эффект на детях */
.card:hover .card-image {
transform: scale(1.08);
}
.card:hover .card-title {
color: #FE3904;
}
.card:hover .card-arrow {
transform: translateX(6px);
}
/* Три элемента реагируют одновременно,
но каждый по-своему.
Hover зона — вся карточка. */
Наведите на карточку. Картинка слегка увеличивается (scale). Заголовок краснеет. Стрелка сдвигается вправо. Три элемента реагируют одновременно, но каждый по-своему. При этом hover-зона — вся карточка, а не каждый элемент в отдельности. Это значит, что зрителю не нужно целиться в мелкий заголовок или стрелку, достаточно навести на карточку в любом месте.
Для веб-плаката этот паттерн полезен в интерактивных секциях. Зритель наводит курсор на зону, и несколько элементов внутри неё оживают, подсказывая: «здесь можно что-то сделать».
Transition пишется на элементе, который меняется, а не на родителе. Hover пишется на родителе, указывая на ребёнка через селектор .parent:hover .child. Если перепутать и написать transition на hover — плавным будет только появление эффекта, а исчезновение произойдёт мгновенно.




