BLOG HEADERS 03

How to Ani­mate a Gra­di­ent Mesh

Ani­mat­ed gra­di­ent mesh­es: hip and trendy, but real­ly hard to get right. Here’s how to do it with­out wreck­ing site performance.





Introduction

With the boon of animated gradient meshes comes the curse of high gpu-usage and dropped frames. Ambitious visual designers often create designs that exceed the technological constraints that front end designers work with.

A great example of this is the free form gradient tool in illustrator, which has no direct translation into css. To code and even to animate that gradient takes a lot of preplanning and strategy that a lot of Front End Designers just don't have time for.

With this blog post, we'll uncover the technological constraints that make gradient meshes difficult to code. Then I'll show four implementations that progressively become more and more performant.

Check out the final codepen example.

What is a Gradient Mesh?

Typical freeform gradient with yellow, pink, purple, and teal

Your typical freeform gradient in Adobe Illustrator has a default four "nodes" where each color stop is located. Illustrator then blends the color that radiates from each node as it meets other colors. For this reason, we'll use radial gradients to function as our nodes of color.

Building a CSS-Only Gradient Mesh

We can do this in CSS by layering multiple radial-gradients within the background-image property. To do this in one line, we separate each radial-gradient with commas, write to the optional location property, and set a transparent color stop for each one. For the best blending experience, let's work in the HSLA (Hue, Saturation, Lightness, Alpha) color model.

Avoid using the "transparent" keyword inside your radial-gradient, as many browsers render transparent gradients through a lot of grays to a transparent black.

We also need to define our base color, which provides a general hue for the entire blend space. This should be a tinted gray or white, where the color is determined by what values you are already working with.

background-color: hsla(42, 100%, 98%, 1) background-image: radial-gradient(at 20% 20%, hsla(28,100%,74%,1) 0%, hsla(28,100%,74%,0) 50%), radial-gradient(at 80% 20%, hsla(189,100%,56%,1) 0%, hsla(189,100%,56%,0) 50%), radial-gradient(at 80% 20%, hsla(355,85%,93%,1) 0%, hsla(355,85%,93%,0) 50%), radial-gradient(at 80% 80%, hsla(340,100%,76%,1) 0%, hsla(340,100%,76%,0) 50%)

First Render

Looks complicated in the text editor, but let's see how that renders:

See the Pen Static Gradient Mesh by Cody (@codyhopper) on CodePen.

Excellent! We have successfully recreated a freeform gradient entirely in CSS. Next, we'll focus just on how to animate the mesh sustainably.

Choosing What to Animate

We have a lot of options for what we choose to move when it comes to these gradient meshes.

Applying Keyframes to 'Background-Image'

Our first option would be to build an animation in css only, where each "frame" of the animation would be a keyframe written in the standard css syntax. With this method, we will continuously update the background-image property.

See the Pen Animated Gradient Mesh by CSS Animation by Cody (@codyhopper) on CodePen.

Now the first problem here is that this approach makes each keyframe static, and the structure imposed by CSS prevents any tweening between keyframe values.

Managing Keyframes with Animejs

Let's dig into some javascript to solve this keyframe problem for our gradient mesh. To do this, we'll install AnimeJS. If you're not already familiar with this animation library, don't worry. What we'll be doing here uses just the basics and can easily be adapted from the excellent AnimeJS documentation.

Refactor with Custom CSS Variables

Before adding AnimeJS to our project, we'll refactor our css to use custom CSS Variables. By abstracting out the position values, we'll have a clean entry point for the anime random() function. Note that we're still seeing jumps between keyframes.

See the Pen Animated Gradient Mesh by CSS Variables by Cody (@codyhopper) on CodePen.

Animating a Gradient with AnimeJS

AnimeJS is a powerful animation library that has the exact tools we need to beautifully animate our css gradient with custom css variables. Since we already have our code refactored to use css variables, all we need is for our javascript to update those variables at each keyframe.

The first thing we'll do with our javascript is locate our gradient, then build it out into an object by setting default property values [see: lines 1–10]. Inside our animation, we declare our target and set up the animation style with duration, direction, and easing.

Finally, we'll use the keyframe syntax that AnimeJS provides to update each value over however many keyframes you want to add. In our next iteration, we'll optimize how these values work.

See the Pen Animated CSS Gradient Mesh via CSS Custom Variables by Cody (@codyhopper) on CodePen.

Introducing Random()

Looking good! Now let's make this a generative animation by leveraging anime's random function. To do this, we'll expand our javascript object by nesting a unique random function in the place of each keyframe value.

We can optimize this even further with some basic math by setting a maximum and minimum position variable along with a wander factor to programmatically control the range of each gradient node.

Finally, we use the "update()" function in AnimeJS to export these new values to our HTML element so they can be picked up by that element's CSS. This works to create a separation of concerns, like if we had multiple gradients animating on the page.

See the Pen Animated CSS Gradient Mesh via CSS Custom Variables with Random by Cody (@codyhopper) on CodePen.

Animating the Gradient Mesh Spread

After adding randomization to position, we can easily apply the same process to the spread of each gradient node by manipulating the size value in our css.

As before, we'll first refactor our CSS to use custom CSS variables in place of a hardcoded value. Then with AnimeJS we'll implement the randomization feature along with minimum and maximum values for size.

See the Pen Animated Gradient Mesh 2.2 by Cody (@codyhopper) on CodePen.

Conclusion

By leveraging custom css variables and the powerful AnimeJS framework, we've developed a smart and performant animated css gradient mesh or freeform gradient.

With the bonus of the random function in anime, and with the way we kept a separation of concerns, if multiple gradients show up on a page, they'll each have their own unique animation and feel.

But we're not done here! What would it look like if we could randomize the colors used? Or, what could we do with more/less keyframes for the property values? There's a ton more to discover here, so fork the final codepen and see what you can come up with!

If you've enjoyed this blog post and want to read more, let me know by email through my about page. Thank you so much for reading and have a great day!