How To Use CSS Custom Properties With Transitions, Transforms, and Animations

The same way you can’t make changes to preprocessed variables inside @media queries, you can’t make changes to them inside @keyframes either. CSS custom properties don’t have the same limitation and can be combined with transitions, transforms, and @keyframe animation for some interesting results.

I’ve been talking about custom properties for the last month or so. I began by showing you how to define and use them before several posts with examples to make your code more readable, to work with custom properties inside @media queries, and finally how to modify custom property values with and without the use of Javascript.

Today I want to present examples that combine custom properties with transitions, transforms, and animations. Because the examples often require a bit of code and because the point of this post isn’t to teach animation, I’ll present a simple example or two and talk about the basic concepts behind a number of Codepen examples.

If you want to learn more about transitions, transforms, and animation you can read some of my previous posts.

Even better, you can buy my book that covers all three in greater depth.

Modifying an Animation with Pseudo Elements

Let’s start with a simple example from François Remy, that I modified just a bit. We’re going to write some code to make an object bounce up and down and then increase how much it bounces when we hover over it.

The HTML is pretty simple. All we need is a div with a class of bounce.

1
<div class="bounce"></div>

I gave the div a width and height, added a 50% border-radius to turn a square into a circle, and gave it a red background. I also used auto margins to center the “ball” horizontally on the page.

I then called an animation named bounce, told it to run for 6 seconds and to repeat the animation indefinitely. Finally I defined a custom property –bounce-distance with a value of 5px.

1
2
3
4
5
6
7
8
9
10
.bounce {
  width: 12.5em;
  height: 12.5em;
  border-radius: 50%;
  background: red;
  margin: 5em auto;

  animation: bounce 0.6s infinite;
  --bounce-distance: 5px;
}

The @keyframe animation is a series of translationY() transforms. At 0% and 100% the circle remains where it’s originally located, but at 33% and 66% the circle is translated by an amount equal to the –bounce-distance. It moves up at 33% and down at 66%.

Notice that both transforms are controlled by the –bounce-distance inside a calc() function and notice that I used a fallback value when calling the custom property.

1
2
3
4
5
6
@keyframes bounce {
  0% { transform: translateY(0px); animation-timing-function: ease-out; }
  33% { transform: translateY(calc(+1 * var(--bounce-distance, 5px))); animation-timing-function: ease-in-out; }
  66% { transform: translateY(calc(-1 * var(--bounce-distance, 5px))); animation-timing-function: ease-in-out; }
  100% { transform: translateY(0px); animation-timing-function: ease-in; }
}

The result of all this code should be a red circle that moved up and down and appears to be bouncing.

We can easily change how much the circle bounces by redefining the –bounce-distance and we’ll do that on :hover.

1
2
3
.bounce:hover {
  --bounce-distance: 25px;
}

If you run the code and move your cursor over the circle, the amount of “bounce” will increase for 5px to 25px.

It’s a simple example and not all that different from examples I showed last week. Here’s a more complex example that uses SVG and redefines a number of SVG properties on “hover to change the image.

While this example certainly changes more than the bouncing ball example, the changes are the same as the simpler example.

A number of custom properties are defined inside :root and then given new values on the svg element. The custom properties are used as attributes in the HTML to set the color of different parts of the SVG.

The custom properties are then redefined and given new values for svg:hover.

CSS Custom Properties and Click Events

Redefining custom properties on pseudo elements isn’t the only way to make changes. Click events can also be used. Here’s an example that makes use of a click event to change a design from a day theme to a night theme.

Clicking the word Sunrise/Sunset will trigger the checked state of the other and lead to the use of a different set of colors to create a day and night theme. The values of the custom properties –sunrise and –sunset are reversed depending on which receives the click event and those values are used throughout the remainder of the code.

There’s a lot going on to create the image itself, but the basic idea is that one set of colors defined as custom properties is used to display the image as a sunrise and another set is defined for sunset.

Here’s an example from Dan Wilson that uses a Javascript click event instead of a CSS click event to pause different parts of the animation.

The animation changes the size and color of a square and provides a pair of checkboxes, one to pause the change in size and one to pause the change in color. Custom properties for the –clip-play-state and –color-play-state are defined in the CSS as running. A Javascript event listener runs a function that updates the value based on the current state of the checkboxes.

While Javascript is used to change the values, you should be able to change the example so it works using the checkbox click event instead.

Changing CSS Custom Properties Based on Cursor location

Another potential way to update custom property values is through the location of the the visitor’s cursor. Here’s a modified version of an example from Tuts+ where a circle changes it’s location on the screen as your cursor moves.

The HTML is again simple, just a div, this time with a class of ball.

1
<div class="ball"></div>

My slightly modified version of the original CSS sets dimensions and a border-radius to create a red circle. I also set a translation transform in both the x and y directions that’s based on the custom properties –mouse-x and –mouse-y, which represent the location of the cursor. These values are multiplied by 1px in order to convert them to pixels.

1
2
3
4
5
6
7
8
9
.ball {
  border-radius: 50%;
  height: 12.5em;
  width: 12.5em;
  transform:
    translateX(calc(var(--mouse-x) * 1.0px))
    translateY(calc(var(--mouse-y) * 1.0px));
  background: red;
}

We’ll use Javascript to get the location of the cursor and update the custom properties. First we’ll grab all the styles using documentElement.style and assign them to a variable docStyle. The values of the two custom properties are then updated to equal to e.clientX and e.clientY (the location of the cursor).

As you move your mouse, these values will continue to change and the custom properties will continue to get updated with the new values causing the circle to move around the screen as your cursor moves.

1
2
3
4
5
6
var docStyle = document.documentElement.style;

document.addEventListener('mousemove', function(e) {
 docStyle.setProperty('--mouse-x', e.clientX);
 docStyle.setProperty('--mouse-y', e.clientY);
});

Note that the custom properties weren’t initially defined in the CSS. You can set a custom property and change its values, even if that custom property wasn’t previously defined.

Here’s another example, also from Tuts+ that works the same way. The graphic is more complex, but as with the previous example, Javascript is used to capture mouse movement and based on the location of the cursor, various custom properties used in the creation of the graphic are updated. The result makes it appear as though the dog is following your cursor around the screen.

See the Pen Alex the CSS Husky Reactive by Envato Tuts+ (@tutsplus) on CodePen.

Here’s a similar example from Hubert Souchaud where the graphic changes to follow your mouse movements. The specifics are different, but the basic idea is again Javascript listening for mouse movements and updating the values of custom properties based on the location of the cursor.

See the Pen Sun Ray Ban [test svg+css variables] by Hubert Souchaud (@dmsr) on CodePen.

Here’s one last example based on the location of the cursor. This one comes from Dan Wilson. Instead of listening for mouse movements, it listens for a mouse click and grabs the location of the cursor at the moment of the click and uses the location to update the location of the squares moving around the screen.

See the Pen Jump to Where You Press by Dan Wilson (@danwilson) on CodePen.

Sliders, Clicks, Transforms, and Custom Properties

Last week I showed you an example where I used an HTML color input type to change the values of custom properties. Then I pointed you to a demo that also used an HTML range input type to create a slider that could be used to adjust the size of the font.

Here are two examples that combine sliders with transforms and animation. The first is another example from Tuts+. It uses three sliders to rotate an image around each of the three axes through the rotateX(), rotateY(), and rotateZ() transforms.

See the Pen Animation with CSS Variables by Envato Tuts+ (@tutsplus) on CodePen.

Again, it’s similar to the demo I presented last week. Javascript listens for a change in the slider and updates the value of the either the –x, –y, or –z custom property depending on which was changed. These are the properties that are used in the rotateX(), rotateY(), and rotateZ() transforms that rotate the image around each of the three axis.

The second example also uses three sliders, which are used to adjust the values of three custom properties. The values of the custom properties are used inside translateX(), scale(), and rotate() transforms.

Additional examples

Before I go, here are a few more examples I thought were interesting.

The first is a recent post from Chris Coyier where Chris shows how to create and animate a 3D cube. Here’s the final result and here’s the post where Chris explains how he did it.

The second example, breathe, from Michael Gehrmann, creates six SVG circles and then creates an animation that rotates and translates all of them. A custom property –angle is assigned values based on whether the circle is the first, second, third, and so on.

Closing Thoughts

Hopefully you didn’t mind today’s walkthrough of examples from other developers. Because of the animation, the examples can contain quite a bit of code, but the concepts behind them are relatively simple.

Custom properties are used to define variables that are used in the calculation of some other property. A mechanism (pseudo element, click event, Javascript) is used to modify the value the custom property inside a transform, transition, or @keyframe animation.

That brings me to the end of this short series on CSS custom properties. I hope you agree they have value even if you already use a preprocessor to create variables. I want to get back to website performance so I’ll continue the series I started a few months back and talk about the time to first byte and how you can improve that time to speed up the load time of your site.

Download a free sample from my book, Design Fundamentals.

Leave a Reply

Your email address will not be published. Required fields are marked *