Animate CSS variables
CSS variables are variables that can be defined on a parent element and then referenced throughout its children:
body {
--brand-color: #f00;
}
a {
color: var(--brand-color);
}
The benefit of CSS variables vs variables in CSS pre-processors like SASS is that they’re dynamic, which means they can be updated at runtime.
So in the above example, to change the link color we’d simply change the value of --brand-color
.
Because these values can be changed, they can be animated. In this tutorial we’ll demonstrate how to animate multiple elements on a page by animating a single CSS variable.
CSS
First, open this CodePen to follow along with the tutorial.
As a simple example, we’re going to animate a distance
property. Add that to body
:
body {
--distance: 0px;
}
Now, on the .box
rule add a transform
that uses this distance
:
transform: translateX(var(--distance));
JavaScript
In all the previous Pose tutorials, if we’ve wanted to change a property of an element, we’ve selected the element itself.
With CSS variables, we’re instead going to animate the parent element where the variable is set. Which, in this case, is body
:
const body = document.querySelector('body')
Now define the pose config with a single pose, called right
:
const config = {
right: { '--distance': '100px' }
}
Bring the two together by creating a new poser:
const bodyPoser = pose(body, config)
To trigger the animation, set the pose to “right”:
bodyPoser.set('right')
And that’s it! All four boxes will animate to the right.
Gotchas
There are a couple of points to keep in mind when you animate CSS variables.
Pose can’t infer types
In the example above, we explicitly set --distance
to '100px'
. Usually when animating x
, we’d simply use 100
as a raw number and Pose would infer that we should use pixels.
When you’re animating CSS variables, Pose doesn’t know what you’re going to do with the variable. So we need to manually tell it if we want specific measurements.
CSS variables sometimes contain whitespace
In this CodePen, we’re animating using the --color
variable as initially read directly from the CSS.
Oddly, this read value is sometimes returned with extra whitespace. If you then set the value with the extra whitespace, it breaks! In this example we’re using from
as from.trim()
to fix this, but there is an open issue in the Stylefire to have this fixed.