При работе с интерфейсами часто возникает задача анимировать набор однотипных элементов: список карточек, элементы сетки, пункты меню, изображения галереи. Если запускать анимацию для всех элементов одновременно, результат выглядит плоско и механически. В таких сценариях применяется stagger — механизм последовательной задержки анимации элементов внутри группы.
В Motion One функция stagger позволяет распределять
старт анимации по элементам массива с заданным интервалом, создавая
эффект каскада.
При анимации коллекции элементов каждому элементу назначается одинаковая анимация, но с индивидуальной задержкой.
Логика проста:
Это формирует визуальную волну.
stagger(delay, options?)
delay (number) Базовая задержка между элементами в миллисекундах.
options (object) — необязательный параметр:
startDelay — общая задержка перед стартом всей
группыfrom — точка отсчёта (индекс элемента, центр, конец или
конкретное число)ease — функция распределения задержекimport { animate, stagger } from "motion";
animate(
".item",
{ opacity: [0, 1], transform: ["translateY(20px)", "translateY(0)"] },
{ delay: stagger(100) }
);
Каждый элемент .item будет появляться с задержкой 100 мс
относительно предыдущего.
Motion One автоматически применяет stagger ко всем элементам, подходящим под селектор.
Эквивалентная логика:
const items = document.querySelectorAll(".item");
items.forEach((el, i) => {
animate(
el,
{ opacity: [0, 1] },
{ delay: i * 100 }
);
});
Но stagger заменяет эту ручную арифметику более
декларативной формой.
startDelay задаёт задержку перед запуском всей
группы.
animate(
".card",
{ opacity: [0, 1], y: [20, 0] },
{ delay: stagger(80, { startDelay: 500 }) }
);
В этом случае:
Параметр from определяет, с какого элемента начинается
распределение задержек.
stagger(100, { from: "first" });
Анимация идёт сверху вниз или слева направо — в порядке DOM.
stagger(100, { from: "last" });
Эффект обратного каскада: последний элемент стартует первым.
Используется для:
stagger(100, { from: "center" });
Анимация начинается из центра списка и расходится в обе стороны.
Часто применяется в:
stagger(100, { from: 2 });
Задаёт конкретный индекс, от которого начинается распространение.
Это даёт точный контроль над визуальным акцентом.
ease управляет распределением задержек, а не самой
анимацией.
stagger(100, { ease: "linear" });
Каждый элемент получает равномерную задержку.
stagger(100, { ease: "easeOut" });
Элементы ближе к начальной точке запускаются плотнее, дальше — реже.
Это создаёт более «живой» эффект волны.
stagger не ограничен простыми свойствами. Он работает с любыми анимируемыми параметрами Motion One.
animate(
".box",
{
opacity: [0, 1],
transform: ["scale(0.5)", "scale(1)"]
},
{
delay: stagger(60, { from: "center" }),
duration: 0.6
}
);
Элементы появляются и масштабируются с центровой волной.
Наиболее выразительные результаты достигаются при комбинировании stagger с transform-свойствами.
animate(
".item",
{
opacity: [0, 1],
y: [30, 0]
},
{
delay: stagger(80)
}
);
animate(
".tile",
{
opacity: [0, 1],
scale: [0.8, 1]
},
{
delay: stagger(50, { from: "center" })
}
);
animate(
".cell",
{
opacity: [0, 1],
rotate: [-10, 0]
},
{
delay: stagger(40, { ease: "easeInOut" })
}
);
stagger автоматически масштабируется под размер коллекции.
Если элементов мало — эффект почти незаметен. Если элементов много — возникает выраженная волна.
Это важно учитывать:
При изменении DOM (например, фильтрации списка) stagger пересчитывается заново при повторном вызове animate.
function animateList() {
animate(
".list-item",
{ opacity: [0, 1], x: [-10, 0] },
{ delay: stagger(70) }
);
}
Каждый новый рендер создаёт новый каскад.
Motion One позволяет использовать keyframes внутри stagger-анимации.
animate(
".dot",
{
y: [0, -10, 0],
opacity: [0, 1, 0]
},
{
delay: stagger(50)
}
);
Каждый элемент проходит одинаковый путь, но в разное время.
stagger используется не только для появления, но и для исчезновения.
animate(
".item",
{ opacity: [1, 0], y: [0, 20] },
{ delay: stagger(60, { from: "last" }) }
);
Элементы исчезают снизу вверх.
stagger не создаёт отдельных таймеров для каждого элемента. Вместо этого используется вычисление задержки на основе индекса.
Это делает его:
stagger(5)
Эффект теряется, элементы воспринимаются как почти одновременные.
stagger(500)
Анимация становится разорванной и медленной.
Отсутствие from в сложных сетках приводит к визуальной
неструктурированности.
При работе с изменяемыми интерфейсами stagger часто комбинируется с изменением позиции элементов.
animate(
".card",
{
opacity: [0, 1],
scale: [0.9, 1]
},
{
delay: stagger(80, { from: "center" })
}
);
Такие эффекты часто используются в:
stagger не является просто задержкой. Он формирует структуру восприятия движения.
Через него можно задавать:
В интерфейсной анимации stagger выступает как базовый механизм организации групповой динамики элементов.