CSS custom properties (переменные --var) позволяют
выносить динамические значения из стилей и управлять ими через
JavaScript. В связке с Motion One они становятся полноценными
анимируемыми параметрами, которые можно использовать для создания гибких
интерфейсных эффектов, зависящих от состояния приложения, скролла,
пользовательского ввода и вычисляемых значений.
Motion One поддерживает анимацию custom properties через стандартный механизм CSS-переменных без необходимости дополнительной конфигурации, при условии корректного задания начальных значений и типов.
CSS custom properties не имеют строгого типа по умолчанию. Браузер интерпретирует их как строки, что ограничивает возможность интерполяции. Для анимации требуется явно задать контекст числового или цветового значения.
.box {
--x: 0px;
transform: translateX(var(--x));
}
import { animate } from "motion";
animate(".box", {
"--x": "200px"
});
Motion One автоматически интерполирует числовые значения, если начальное и конечное состояние совместимы по типу.
Наиболее распространённый сценарий — анимация чисел, используемых внутри transform, opacity-подобных эффектов или сложных вычислений.
.card {
--scale: 1;
transform: scale(var(--scale));
}
animate(".card", {
"--scale": 1.2
});
При анимации числовых значений Motion One:
CSS custom properties требуют явного указания единиц измерения, если значение не безразмерное. Несоответствие единиц блокирует интерполяцию.
Корректный пример:
animate(".panel", {
"--offset": "300px"
});
Некорректный вариант:
animate(".panel", {
"--offset": 300
});
В последнем случае значение будет интерпретировано неоднозначно, что может привести к отсутствию плавной анимации.
CSS переменные могут хранить цвета в любом валидном формате:
rgb, rgba, hsl, hex. Motion One
выполняет интерполяцию цветов при совместимых форматах.
.button {
--color: rgb(0, 0, 0);
background: var(--color);
}
animate(".button", {
"--color": "rgb(255, 100, 0)"
});
Для стабильной интерполяции предпочтительно использовать одинаковые цветовые модели на старте и в целевом состоянии.
Custom properties часто применяются как параметры внутри
transform, что позволяет строить сложные анимации без
прямого управления transform через JavaScript.
.avatar {
--x: 0px;
--y: 0px;
transform: translate3d(var(--x), var(--y), 0);
}
animate(".avatar", {
"--x": "120px",
"--y": "-80px"
});
Такой подход обеспечивает:
Motion One поддерживает keyframes для custom properties так же, как и для стандартных CSS свойств.
animate(".box", {
"--progress": [0, 1]
}, {
duration: 1
});
Применение в CSS:
.box {
--progress: 0;
opacity: var(--progress);
}
Keyframes позволяют описывать сложные переходы без ручного вычисления промежуточных значений.
Одновременная анимация нескольких переменных позволяет создавать согласованные эффекты движения и трансформации.
animate(".panel", {
"--x": ["0px", "200px"],
"--opacity": [0, 1],
"--scale": [0.8, 1]
}, {
duration: 0.8,
easing: "ease-out"
});
В этом случае Motion One синхронно обновляет все свойства в одном анимационном тикe, что гарантирует согласованность визуального результата.
Custom properties полностью совместимы с системами easing Motion One. Это позволяет управлять динамикой изменения значений без изменения логики вычислений.
animate(".dot", {
"--x": "400px"
}, {
easing: "ease-in-out",
duration: 1.5
});
Использование сложных easing-кривых особенно эффективно при работе с переменными, управляющими физически похожими эффектами: пружины, инерция, замедление.
Custom properties могут быть привязаны к состоянию приложения и обновляться программно.
const state = { progress: 0 };
function update(value) {
state.progress = value;
animate(".loader", {
"--progress": value
}, {
duration: 0
});
}
При duration: 0 значение обновляется мгновенно, превращая анимацию в реактивное управление стилями.
Motion One позволяет использовать scroll-driven анимации, где CSS переменные становятся посредником между скроллом и визуальными эффектами.
import { animate, scroll } from "motion";
scroll(
animate(".hero", {
"--blur": ["0px", "10px"],
"--scale": [1, 1.2]
}),
{
target: document.querySelector(".hero"),
offset: ["start start", "end start"]
}
);
В этом сценарии custom properties выступают как универсальный слой абстракции для визуальных изменений.
Анимация CSS переменных выполняется на стороне главного потока браузера, но Motion One минимизирует накладные расходы за счёт:
requestAnimationFrameРекомендуемые практики:
transform и opacity внутри
custom propertiesКлючевой аспект работы с custom properties — стабильность типа значения.
Поддерживаемые категории:
0, 1, 0.5)px, rem, %)rgb, hsl, hex)deg, rad)Нестабильные сценарии:
px и %Custom properties часто используются как промежуточный слой для вычислений в CSS.
.progress {
--value: 0;
--angle: calc(var(--value) * 3.6deg);
transform: rotate(var(--angle));
}
animate(".progress", {
"--value": 100
});
Такой подход позволяет делегировать вычисления CSS, оставляя JavaScript только управление состоянием.
Custom properties позволяют создавать сложные композиции без увеличения сложности JS-логики.
.element {
--tx: 0px;
--ty: 0px;
--blur: 0px;
--opacity: 1;
transform: translate(var(--tx), var(--ty));
filter: blur(var(--blur));
opacity: var(--opacity);
}
animate(".element", {
"--tx": "150px",
"--ty": "80px",
"--blur": "6px",
"--opacity": 0.5
});
Такой подход обеспечивает масштабируемость анимационных систем в интерфейсах с высокой плотностью взаимодействий.
Custom properties удобно использовать как слой между состояниями UI и визуальными эффектами.
function setActive(isActive) {
animate(".menu", {
"--active": isActive ? 1 : 0
}, {
duration: 0.3
});
}
.menu {
opacity: calc(0.5 + var(--active) * 0.5);
transform: scale(calc(1 + var(--active) * 0.05));
}
Такой паттерн снижает связанность логики и визуальной части.
При работе с custom properties в Motion One следует учитывать:
calc() должны быть согласованы по
типамСтабильность достигается за счёт явного объявления всех переменных на уровне элемента.
В архитектуре интерфейсов CSS переменные часто выступают как публичный API визуального слоя.
.component {
--x: 0px;
--y: 0px;
--opacity: 1;
}
JavaScript взаимодействует только с этим API:
animate(".component", {
"--x": "100px",
"--opacity": 0.8
});
Такой подход позволяет: