Reusable @keyframes with CSS custom properties
Tags: css, webdev, tutorial
Published: 2020-01-13 11:34:30

In this article, I will share with you an application of CSS custom properties that I have found useful.

If you're like me, who like to cramp as many animations in the page as possible for micro interactions sake (just kidding, don't do that), you would be writing a lot of CSS animations with `@keyframes`.

`@keyframes` is notorious for its inflexibility, once it is declared, the values are then set in stone. If you have a set of `@keyframes` with the same behavior but different values, you'll need to make another set. This result in a lot of `@keyframes` that are similar but with a little variations in the numbers. Let’s take a look at the example below:

```css
@keyframes fade-in {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

@keyframes fade-in-a-little {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 0.3;
  }
}

.item-1 {
  animation: fade-in 300ms ease;
}

.item-2 {
  animation: fade-in-a-little 300ms ease;
}
```

In the example above, we have 2 items with 2 different animations that are similar, with only slight difference in the `opacity` value at `100%`.

Now imagine what this would turn into when applied to more items. As the website scale up, what you'll end up with is 100s of similar `@keyframes`, bloating up the CSS file. We can't have that. 😐

## CSS custom properties to the rescue 
CSS custom properties (also known as CSS variables), are most widely applied for theming. It can also be used to make `@keyframes` reusable! (If you want to learn about CSS custom properties, see [here](https://developer.mozilla.org/en-US/docs/Web/CSS/--*))

Let's refactor our previous example with CSS custom properties!

```css
@keyframes fade {
  0% {
    opacity: var(--fade-start, 0);
  }

  100% {
    opacity: var(--fade-end, 1);
  }
}

.item-1 {
  animation: fade 300ms ease;
}

.item-2 {
  --fade-end: 0.3;
  animation: fade 300ms ease;
}
```

`fade-in-a-little` `@keyframes` is taken out as it is not needed anymore. We now have only 1 set of `@keyframes` `fade`, and apply CSS custom properties to the starting opacity value and the ending opacity value with:

```
opacity: var(--fade-start, 0); // start

opacity: var(--fade-end, 1); // end
```

In this example, we have 2 custom properties: `--fade-start` and `--fade-end`. These variables are applied using `var()` function (read more about it [here](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties)). The `var()` function accepts 2 parameters, a value and a fallback (default value).

So with this line `opacity: var(--fade-start, 0);`, if `--fade-start` is not set, 0 will be applied instead. The same goes to `--fade-end`.

The end result we get here is a set of `@keyframes` that can `fade` between `opacity: 0` and `opacity: 1` by default and be tuned within the scope of a CSS selector. 🤯

Wait... so to fade out? Yes! Instead of declaring another set of `@keyframes` for `fade-out`, you can reuse `fade` and set `--fade-start` as 1, and `--fade-end` to 0, like so:

```css
.item-to-fade-out {
  --fade-start: 1;
  --fade-end: 0;
  animation: fade 300ms ease;
}
```

With CSS custom properties, `@keyframes` can now be function like, where the variable parts can be defined at a later stage, making `@keyframes` reusable. Yay **DRY** ❤️️

## Time to bust out the Codepen
One `@keyframes` to `fade` it all
{% codepen https://codepen.io/jenning/pen/ZEYxNNG %}

# Summary
Fading animation is one of the most common animation on the web, now with CSS custom properties we can reduce our CSS bloat significantly while having as many variations of it as we'd like.

Consider applying this to `@keyframes` that you find yourself repeating a lot with many little variations. 

Hope you'll find this useful!