Работа с выбором элементов в Motion One строится вокруг прямого использования DOM-селекции и гибкого принятия различных типов целей: строк CSS-селекторов, отдельных узлов DOM, коллекций элементов и массивов. Такой подход снимает необходимость в промежуточных абстракциях и позволяет анимации работать с уже существующей моделью документа.
Функции анимации принимают универсальный аргумент
target, который определяет набор элементов для применения
эффекта. Поддерживаются несколько основных форматов:
ElementNodeListHTMLCollectionКаждый из вариантов приводит к одному результату — формированию набора DOM-узлов, к которым применяется анимация.
Наиболее распространённый способ — передача строки CSS-селектора. В
этом случае происходит внутренний вызов
document.querySelectorAll, и анимация применяется ко всем
совпавшим элементам.
import { animate } from "motion";
animate(".box", {
opacity: [0, 1],
transform: ["translateY(20px)", "translateY(0px)"]
});
Селекторы могут быть любыми валидными CSS-выражениями:
animate("section .item", { x: 100 });
animate(".card.active", { scale: 1.1 });
animate("#header nav a", { color: "#ffcc00" });
Такой подход делает систему выбора элементов полностью декларативной и независимой от ручного получения DOM-узлов.
Результаты стандартных DOM-методов также напрямую поддерживаются:
const items = document.querySelectorAll(".item");
animate(items, {
opacity: [0, 1],
y: [30, 0]
});
NodeList автоматически интерпретируется как набор целей
без необходимости преобразования в массив.
Аналогично работает HTMLCollection:
const children = document.getElementsByClassName("box");
animate(children, {
scale: 0.9
});
Внутренне такие коллекции нормализуются в единый массив элементов, что обеспечивает единообразное применение анимации.
Для точечного управления используется передача конкретного DOM-узла:
const button = document.querySelector("button");
animate(button, {
scale: 0.95
});
Такой способ предпочтителен, когда элемент уже заранее найден или хранится в переменной состояния приложения.
Допускается явная передача массива DOM-элементов. Это полезно при сложной логике отбора, фильтрации или комбинировании разных источников:
const cards = [
document.querySelector(".card-1"),
document.querySelector(".card-2"),
document.querySelector(".card-3")
];
animate(cards, {
rotate: 5
});
Массивы обрабатываются так же, как и DOM-коллекции, без дополнительной трансформации.
Часто требуется объединить несколько источников элементов. В таких случаях применяется ручное объединение:
const primary = document.querySelectorAll(".primary");
const secondary = document.querySelectorAll(".secondary");
animate([...primary, ...secondary], {
opacity: 0.6
});
Spread-оператор обеспечивает объединение в единый массив целей.
Передача селектора в виде строки означает, что выборка выполняется каждый раз при вызове анимации. Это важно в динамических интерфейсах, где DOM может изменяться:
animate(".notification", {
x: 50
});
Если новые элементы с классом .notification появляются
после первого вызова, следующий вызов автоматически их захватит.
При необходимости фиксированного набора элементов используется предварительное сохранение:
const notifications = document.querySelectorAll(".notification");
function show() {
animate(notifications, { opacity: 1 });
}
Такой подход исключает повторные DOM-запросы и стабилизирует набор целей.
В случаях, когда требуется ограничить область поиска, используется
метод querySelector/querySelectorAll от
конкретного контейнера:
const modal = document.querySelector(".modal");
animate(modal.querySelectorAll(".item"), {
y: -10
});
Таким образом формируется локальная область анимации без влияния на глобальный DOM.
CSS-селекторы позволяют описывать иерархии и состояния элементов:
animate(".list > li:first-child", { x: 20 });
animate(".grid .cell:nth-child(3)", { scale: 1.2 });
Поддержка стандартного CSS-синтаксиса делает выборку предсказуемой и совместимой с привычной моделью браузера.
Селекторы с псевдоклассами позволяют реагировать на состояние элементов:
animate("button:hover", {
scale: 1.05
});
animate("input:focus", {
borderColor: "#4a90e2"
});
Такие селекторы полезны при построении декларативных эффектов, завязанных на пользовательское взаимодействие.
Иногда требуется дополнительная логика после получения NodeList:
const items = [...document.querySelectorAll(".item")];
const activeItems = items.filter(el => el.classList.contains("active"));
animate(activeItems, {
opacity: 1
});
Фильтрация позволяет отделять визуально активные или логически значимые элементы перед анимацией.
Использование строковых селекторов приводит к повторному выполнению DOM-запросов. При большом количестве анимаций это может стать узким местом.
Практика оптимизации:
querySelectorAll при повторном
использовании*,
body *)Часто встречаются ситуации, когда набор элементов оказывается неожиданным:
null из querySelector вызывает
отсутствие эффектаHTMLCollection) может
давать изменяющийся результат при мутациях DOMВнутри механизма анимации все входные значения приводятся к единому виду — массиву DOM-элементов. Это обеспечивает одинаковое поведение независимо от источника:
querySelectorAllNodeList → массивHTMLCollection → массивElement → массив из одного элементаТакая унификация исключает необходимость ручной обработки типов перед запуском анимации.
В сложных приложениях селекторы становятся частью архитектуры UI. Они позволяют связывать структуру DOM с анимационной логикой без дополнительных слоёв абстракции:
animate(".sidebar .menu-item", {
x: [-10, 0],
opacity: [0, 1]
});
animate(".content article", {
y: 20
});
Чем более структурирован DOM, тем точнее становится управление анимациями через селекторы.
Селекторы могут использоваться как единый источник истины для повторяющихся анимаций:
const ITEM_SELECTOR = ".timeline-item";
function animateIn() {
animate(ITEM_SELECTOR, { opacity: 1, y: 0 });
}
function animateOut() {
animate(ITEM_SELECTOR, { opacity: 0, y: 20 });
}
Такой подход снижает дублирование строк и упрощает поддержку интерфейса.