Как сделать "как у Тинькофф/Яндекса": анимации и микро-интеракции, которые сразу делают приложение "дорогим"
Не нужно быть дизайнером или знать 3D. Простые CSS-анимации и JavaScript-трюки, которые сразу поднимают уровень вашего приложения. Пошаговый гид с кодом и объяснениями — от кнопок до модальных окон.
Замечали, как приложения Тинькофф, Яндекса или Альфа-Банка просто приятно использовать? Кнопки отзываются на нажатия, элементы плавно появляются, загрузки не бесят, а наоборот — радуют глаз. Это не магия и не армия дизайнеров. Это набор конкретных приёмов, которые можете освоить и вы.

Почему это вообще важно?
Пользователь не скажет: "Ого, тут transition с cubic-bezier!". Но он скажет: "Какое приятное приложение" или "Как-то дёшево выглядит". Качественные анимации работают на подсознательном уровне:
Создают ощущение скорости — даже если сервер тормозит
Дают обратную связь — пользователь понимает, что его действие учтено
Снижают когнитивную нагрузку — плавные переходы помогают мозгу понять, что происходит
Вызывают доверие — детали показывают, что команда заботится о продукте
1. Скелетоны вместо спиннеров
Что не так со спиннерами?
Крутящийся кружок не даёт никакой информации. Пользователь не знает, сколько ждать и что вообще грузится.
Что делают в Тинькофф:
Показывают "призрак" будущего контента — серые блоки на месте текста, картинок, кнопок. Это называется skeleton screen или скелетон.
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: 4px;
}
@keyframes loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}Почему это работает:
Мозг воспринимает скелетон как "контент уже почти загрузился", а не "придётся ждать неизвестно сколько". По исследованиям, пользователи оценивают время загрузки со скелетонами на 30-40% быстрее, чем со спиннерами.
2. Тактильный отклик на действия
Эффект нажатия на кнопку:
Когда вы нажимаете кнопку в приложении Яндекса, она немного "проваливается". Это имитирует физическую кнопку.
.button {
background: #ffdd2d;
border: none;
padding: 12px 24px;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}
.button:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}Ripple-эффект (волна):
При клике от точки нажатия расходится волна. Это фишка Material Design, но её используют все.
function createRipple(event) {
const button = event.currentTarget;
const circle = document.createElement('span');
const diameter = Math.max(button.clientWidth, button.clientHeight);
const radius = diameter / 2;
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - button.offsetLeft - radius}px`;
circle.style.top = `${event.clientY - button.offsetTop - radius}px`;
circle.classList.add('ripple');
const ripple = button.getElementsByClassName('ripple')[0];
if (ripple) {
ripple.remove();
}
button.appendChild(circle);
}3. Умные переходы между состояниями
Плохо:
Контент просто исчезает и появляется. Резко. Дёшево.
Хорошо:
Используем плавные переходы с transform и opacity.
.fade-enter {
opacity: 0;
transform: translateY(10px);
}
.fade-enter-active {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-enter-to {
opacity: 1;
transform: translateY(0);
}Золотое правило: Любое изменение DOM должно быть анимировано. Никаких резких появлений/исчезновений.
4. Микро-анимации форм
При фокусе на input:
.input {
border: 2px solid #e0e0e0;
padding: 12px;
width: 100%;
transition: all 0.2s ease;
outline: none;
}
.input:focus {
border-color: #ffdd2d;
box-shadow: 0 0 0 4px rgba(255, 221, 45, 0.1);
}
.input-label {
position: absolute;
left: 12px;
top: 12px;
color: #999;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
}
.input:focus + .input-label,
.input:not(:placeholder-shown) + .input-label {
top: -8px;
left: 8px;
font-size: 12px;
background: white;
padding: 0 4px;
color: #ffdd2d;
}Валидация с анимацией:
.input-error {
border-color: #ff3333;
animation: shake 0.4s;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}5. Прогресс-бары, которые не бесят
Плохой прогресс-бар: просто движется. Скучно.
Хороший прогресс-бар: плавный, с небольшим свечением, показывает конкретные этапы.
.progress-bar {
width: 100%;
height: 6px;
background: #f0f0f0;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #ffdd2d, #ffc700);
border-radius: 10px;
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
box-shadow: 0 0 10px rgba(255, 221, 45, 0.5);
}6. Модальные окна с умным появлением
Неправильно: окно просто появляется.
Правильно: фон затемняется, окно появляется с лёгким масштабированием и движением снизу вверх.
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0);
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s ease;
pointer-events: none;
}
.modal-overlay.active {
background: rgba(0, 0, 0, 0.5);
pointer-events: all;
}
.modal {
background: white;
border-radius: 16px;
padding: 24px;
max-width: 500px;
width: 90%;
transform: scale(0.9) translateY(20px);
opacity: 0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.modal-overlay.active .modal {
transform: scale(1) translateY(0);
opacity: 1;
}
7. Карточки с hover-эффектами
Карточки товаров, постов, проектов — они должны реагировать на наведение:
.card {
background: white;
border-radius: 12px;
padding: 20px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
.card img {
transition: transform 0.3s ease;
}
.card:hover img {
transform: scale(1.05);
}8. Индикаторы загрузки для действий
Когда пользователь нажимает "Отправить", кнопка должна показать, что процесс идёт:
.submit-button {
position: relative;
min-width: 120px;
transition: all 0.3s ease;
}
.submit-button.loading {
pointer-events: none;
}
.spinner {
width: 20px;
height: 20px;
animation: rotate 1s linear infinite;
}
@keyframes rotate {
100% { transform: rotate(360deg); }
}9. Тосты и уведомления
Принципы:
Появляются сбоку (справа или слева сверху)
Плавно въезжают
Автоматически исчезают через 3-5 секунд
Можно закрыть вручную
.toast {
position: fixed;
top: 20px;
right: -300px;
background: white;
padding: 16px 20px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
min-width: 250px;
transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.toast.show {
right: 20px;
}10. Важные принципы анимаций
Timing functions (функции времени):
Не используйте просто ease или linear. Изучите cubic-bezier:
ease-in-out — плавно ускоряется и замедляется
cubic-bezier(0.4, 0, 0.2, 1) — Material Design easing, очень приятный
cubic-bezier(0.25, 0.46, 0.45, 0.94) — easeOutQuad для быстрых анимаций
Длительность:
Микро-интеракции (hover, клики): 100-200ms
Переходы между состояниями: 200-300ms
Модальные окна, drawer'ы: 300-400ms
Анимации страниц: 400-600ms
Больше 600ms — уже слишком медленно.
Правило 60 FPS:
Анимируйте только свойства, которые не вызывают reflow:
✅
transform,opacity❌
width,height,top,left,margin
Заключение
Качественные анимации — это не про сложность, а про детали. Вам не нужно изучать 3D или физику. Нужно просто:
Добавить плавность ко всему
Давать обратную связь на действия
Использовать правильные timing functions
Быть консистентным
Начните с одной кнопки. Сделайте её приятной. Потом ещё одну. Потом формы. Потом карточки. Через месяц ваше приложение будет выглядеть на миллион.
Всё это и намного больше можно изучить в Кодике — подробно, с практическими заданиями и реальными примерами. Мы разбираем не только теорию, но и показываем, как всё это работает в реальных проектах.
А если нужна поддержка, вопросы или хочется обсудить код — у нас есть огромное активное комьюнити в Telegram-канале! Больше 2000 разработчиков, которые всегда помогут, подскажут и поддержат.