Как задать универсальный @keyframes для нескольких разных блоков, без скриптов?

Универсальные @keyframes для нескольких блоков в CSS

Для создания универсальной анимации, которая может применяться к нескольким разным блокам без использования JavaScript, существует несколько эффективных подходов. Рассмотрим их подробно.

1. Базовый подход с общими keyframes

Создайте общие keyframes, которые можно применять к разным элементам:

/* Универсальные keyframes */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slideIn {
  from { transform: translateY(50px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.05); }
  100% { transform: scale(1); }
}

/* Применение к разным элементам */
.block-1 {
  animation: fadeIn 1s ease-in-out;
}

.block-2 {
  animation: slideIn 0.8s ease-out;
}

.block-3 {
  animation: pulse 2s infinite;
}

2. Использование CSS-переменных для настройки

Для большей гибкости используйте CSS-переменные (custom properties):

:root {
  --anim-duration: 1s;
  --anim-delay: 0s;
  --anim-timing: ease;
}

@keyframes universalAnimation {
  0% {
    opacity: var(--anim-start-opacity, 0);
    transform: var(--anim-start-transform, translateY(20px));
  }
  100% {
    opacity: var(--anim-end-opacity, 1);
    transform: var(--anim-end-transform, translateY(0));
  }
}

/* Применение с разными настройками */
.element-a {
  --anim-duration: 0.5s;
  --anim-start-opacity: 0.5;
  animation: universalAnimation var(--anim-duration) var(--anim-timing);
}

.element-b {
  --anim-duration: 2s;
  --anim-start-transform: translateX(-50px);
  --anim-delay: 0.5s;
  animation: universalAnimation var(--anim-duration) var(--anim-timing) var(--anim-delay);
}

3. Комбинированный подход с классами-модификаторами

/* Базовые keyframes */
@keyframes baseAnimation {
  0% { opacity: 0; transform: scale(0.8); }
  100% { opacity: 1; transform: scale(1); }
}

/* Базовый класс анимации */
.animate {
  animation: baseAnimation 0.6s var(--anim-easing, ease-out) forwards;
}

/* Модификаторы */
.animate--slow {
  --anim-duration: 1.2s;
}

.animate--fast {
  --anim-duration: 0.3s;
}

.animate--bounce {
  --anim-easing: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.animate--delay {
  animation-delay: 0.5s;
}

4. Универсальные keyframes с параметризацией

@keyframes dynamicMove {
  from {
    transform: 
      translateX(var(--move-start-x, 0)) 
      translateY(var(--move-start-y, 0));
    opacity: var(--start-opacity, 0);
  }
  to {
    transform: 
      translateX(var(--move-end-x, 0)) 
      translateY(var(--move-end-y, 0));
    opacity: var(--end-opacity, 1);
  }
}

/* Использование */
.card {
  --move-start-y: 30px;
  --start-opacity: 0;
  animation: dynamicMove 0.8s ease-out;
}

.modal {
  --move-start-x: -100px;
  --move-end-x: 0;
  animation: dynamicMove 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

5. Анимация с наследованием свойств

@keyframes inheritAnimation {
  0% {
    opacity: inherit;
    transform: inherit;
    /* Другие наследуемые свойства */
  }
  100% {
    opacity: inherit;
    transform: inherit;
  }
}

.animated-element {
  /* Задаем начальные и конечные значения через наследование */
  animation: inheritAnimation 1s;
  animation-fill-mode: both;
}

.animated-element::before {
  content: "";
  opacity: 0;
  transform: translateY(20px);
}

.animated-element::after {
  content: "";
  opacity: 1;
  transform: translateY(0);
}

6. Практический пример с несколькими элементами

<div class="container">
  <div class="box box-1">Элемент 1</div>
  <div class="box box-2">Элемент 2</div>
  <div class="box box-3">Элемент 3</div>
</div>
:root {
  --anim-duration: 0.8s;
  --anim-timing: ease-out;
}

@keyframes universalAppear {
  from {
    opacity: 0;
    transform: 
      translateY(var(--start-y, 20px)) 
      scale(var(--start-scale, 0.95));
  }
  to {
    opacity: 1;
    transform: 
      translateY(0) 
      scale(1);
  }
}

.box {
  animation: universalAppear var(--anim-duration) var(--anim-timing);
  animation-fill-mode: both;
}

.box-1 {
  --start-y: 30px;
  --start-scale: 0.9;
  animation-delay: 0.1s;
}

.box-2 {
  --start-y: -30px;
  --start-scale: 1.1;
  animation-delay: 0.2s;
}

.box-3 {
  --start-y: 0;
  --start-scale: 0.8;
  animation-delay: 0.3s;
}

7. Расширенный пример с медиа-запросами

@keyframes responsiveAnimation {
  0% {
    opacity: var(--anim-start-opacity, 0);
    transform: 
      translateX(var(--anim-start-x, 0)) 
      translateY(var(--anim-start-y, 0)) 
      scale(var(--anim-start-scale, 1));
  }
  100% {
    opacity: var(--anim-end-opacity, 1);
    transform: 
      translateX(var(--anim-end-x, 0)) 
      translateY(var(--anim-end-y, 0)) 
      scale(var(--anim-end-scale, 1));
  }
}

.element {
  animation: responsiveAnimation 0.6s ease-out;
}

/* Адаптивные настройки */
@media (max-width: 768px) {
  .element {
    --anim-start-y: 20px;
    --anim-start-scale: 0.95;
  }
}

@media (min-width: 769px) {
  .element {
    --anim-start-x: -50px;
    --anim-start-scale: 0.9;
  }
}

Преимущества такого подхода:

  1. Переиспользуемость - одна анимация для множества элементов
  2. Гибкость - настройка через CSS-переменные
  3. Производительность - меньше кода, лучше оптимизация
  4. Поддержка - работает во всех современных браузерах
  5. Адаптивность - легко настраивается под разные экраны

Рекомендации:

  • Используйте will-change для оптимизации производительности
  • Тестируйте анимации на разных устройствах
  • Учитывайте доступность (prefers-reduced-motion)
  • Используйте appropriate timing functions для естественного движения

Этот подход позволяет создавать сложные, универсальные анимационные системы без использования JavaScript, что улучшает производительность и упрощает поддержку кода.