Продвинутые CSS-анимации: keyframes против transitions

Keyframes vs Transitions: Вечная битва за плавный интерфейс

Присаживайся, коллега. Давай честно: сколько раз ты проклинал CSS, когда пытался сделать простую анимацию появления модалки? Ты вешаешь transition: all 0.3s, меняешь display: none на block, и… ничего. Никакой плавности, просто резкий скачок. Ты лезешь в JavaScript, вешаешь setTimeout на 10 миллисекунд или слушаешь событие transitionend, превращая код в спагетти. Знакомая боль?

Сегодня мы разберем, когда пора перестать мучить transitions и переходить на keyframes, а также заглянем в светлое будущее, где старые костыли больше не нужны.

Как мы страдали раньше

Раньше мир CSS-анимаций был жестко разделен. Transitions были идеальны для простых состояний: навел мышкой — кнопка плавно поменяла цвет. Но как только дело доходило до многоэтапных движений или анимации свойств, которые не имеют промежуточных значений (типа того же display), начинался ад.

Мы использовали хаки с max-height: 0 и max-height: 1000px для раскрывающихся списков, потому что CSS не умел анимировать высоту в auto. Мы создавали невидимые элементы, чтобы браузер заранее просчитал их геометрию. А если нужно было сделать бесконечную сложную пульсацию, приходилось городить огромные конструкции в @keyframes, которые было чертовски сложно переиспользовать. Кстати, если ты до сих пор борешься с прыгающей версткой при изменении контента, посмотри, как свойство aspect-ratio решает проблемы с пропорциями — это база для стабильных анимаций.

Как делать правильно в 2026 году

Современный CSS (тот, что мы называем спецификацией 2024-2026 годов) наконец-то принес «киллер-фичи», которые стирают грань между переходами и ключевыми кадрами. Теперь мы можем анимировать даже те вещи, которые раньше считались невозможными.

Главные герои нашего времени: @starting-style и свойство transition-behavior: allow-discrete. Они позволяют анимировать переход элемента из состояния «его нет в DOM/он скрыт» в состояние «он виден». Это особенно круто работает, когда ты используешь нативные элементы dialog и popover. Теперь не нужно гадать, победит ли opacity в битве с display: none — браузер сам поймет, что нужно сначала дождаться завершения анимации, а потом уже скрывать элемент.

Transitions теперь выбираем, когда нужно простое взаимодействие «А в Б», даже если это сложные типы данных. А Keyframes оставляем для цикличных, нелинейных анимаций или когда элемент должен пройти через несколько опорных точек без участия пользователя.

Готовый сниппет кода

Давай посмотрим на магию в деле. Вот пример современной анимации появления элемента, который раньше потребовал бы кучу JS-кода, а теперь работает на чистом CSS:


/* Стили для элемента, который появляется плавно из display: none */
.modern-card {
  display: none;
  opacity: 0;
  transform: translateY(20px) scale(0.9);
  transition: 
    display 0.5s allow-discrete, 
    opacity 0.5s, 
    transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Состояние, когда элемент открыт (например, через класс или [open]) */
.modern-card.is-visible {
  display: block;
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* Магия: задаем начальные значения для анимации ПЕРЕД тем, как элемент появится */
@starting-style {
  .modern-card.is-visible {
    opacity: 0;
    transform: translateY(20px) scale(0.9);
  }
}

/* Бонус: анимация высоты до auto (теперь в современных браузерах) */
.accordion-content {
  height: 0;
  overflow: hidden;
  transition: height 0.3s interpolate-size;
}

.accordion-content.open {
  height: auto;
}

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

Самый частый «выстрел в ногу» — это анимация «тяжелых» свойств. Новички обожают анимировать width, height, top или margin. Проблема в том, что каждое изменение этих свойств заставляет браузер пересчитывать всю геометрию страницы (Layout/Reflow). Если у тебя на странице больше десяти элементов, анимация начнет безбожно тормозить, особенно на мобилках.

Золотое правило: анимируй только transform (scale, translate, rotate) и opacity. Эти свойства обрабатываются видеокартой (GPU) и не трогают макет страницы. Если тебе нужно изменить размер кнопки — используй transform: scale(). Если нужно передвинуть блок — transform: translate(). Твой интерфейс должен летать, а не ползать со скоростью 15 FPS.

🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!

🚀 Прокачай свой код

Готовые CSS-сниппеты, разбор продвинутых фишек и эксклюзивные материалы — в нашем Telegram-канале.

Подписаться
error: Content is protected !!
Прокрутить вверх