A tale of two animations – the compositor in the skies
calendar.perfplanet.com·5h
💨Tailwind
Preview
Report Post

My website has an animation of clouds moving across the screen. It formerly had an animation of a sun with pulsing waves which is now static. An important performance consideration decided how this came to be in my small website: the almighty compositor.

This article is intended to be an approachable story and practical example of how the compositor can help improve CSS animation performance and also presents limitations for animating.

Let my website update serve as a lesson: consider the compositor early on in your project if you want super efficient animations. Sometimes you can quickly update a non-composited animation, sometimes not.

What is a

My website has an animation of clouds moving across the screen. It formerly had an animation of a sun with pulsing waves which is now static. An important performance consideration decided how this came to be in my small website: the almighty compositor.

This article is intended to be an approachable story and practical example of how the compositor can help improve CSS animation performance and also presents limitations for animating.

Let my website update serve as a lesson: consider the compositor early on in your project if you want super efficient animations. Sometimes you can quickly update a non-composited animation, sometimes not.

What is a compositor?

You might be better suited to investigate this yourself depending on your skill level. I know many of the words but the concepts are somewhat advanced.

Today’s article is a simplified ‘high level’ explanation of the feature meant to speak right down to earth to assist an entry level CSS developer:

The Compositor GPU is a separate thread which allows for limited kinds of better performing animations than on the main thread

In common language you might say the compositor it has its own engine and keeps things clean… it has a power source that avoids side effects or pollution in the main thread as much. I have probably misused a word already, but it seems truthy enough for my hard and quick lesson of its power albeit with a limited selection of properties:

There are only a few properties that can be handled by the compositor alone. Today there are only two properties for which that is true – transforms and opacity.

There is a measurable difference between running a non-composited animation and composited animation, as I learned.

The update

I was proud to show off some cleverness with a little redesign of my website. I found some amazing simple cloud graphics from an older project I was working on. I also found a codepen with a sun with a pulsing ray animation.

Sure enough, I slapped both onto my website and updated and launched it. The sun was shining, the clouds were moving… but all was not well as I learned…

An inspirational web development figure showed me a screenshot of their Chrome performance tab. My website was making some noise in the main thread of the performance tab that I didn’t expect:

Noisy Skies

As the cloud and sunshine animations ran, sure enough it was clear slivers of activity were visible over and over across the main thread- the green strips of activity in that screenshot. I felt aghast at a mentor finding this noisy rip in fabric of my tiny website that I had updated so easily and somewhat carelessly.

Not only did the animation cause noise in the performance tab, it seemed to run over and over without limit. Just not really ideal. I had to impress the master and rectify my animations. What was going on?

The Clouds

The root of my cloud “flare” of main thread animation activity was related to a keyframes definition that was changing the left property:

 @keyframes cloud_floating { 0% { left: -50% } to { left: 105% } } 

The original animation I took inspiration from used this left property keyframes definition to move horizontally across the screen. It maybe didnt have a noticeable slowing impact problem as a user necessarily but it was definitely leaking and causing excess compute and “thrashing”.

Compositing the Clouds

I learned sometimes it is possible to convert a simple non composited animation to use the compositor only and to do it fast. It was a memorable moment of the year as I figured this out with the help of the docs. I did it so fast the master was still finishing the coffee they had started when they told me the performance problem:

Using compositor only properties:

 @keyframes cloud_floating { 0% { transform: translateX(-50%); } 100% { transform: translateX(105%); } } 

One of the clouds CSS updated with will-change:

 .cloud.one { animation-duration: 120s; animation-delay: -80s; top: -7vw; width: calc(241 * 1vw * 0.125); max-width: 28rem; will-change: transform; } 

In basic terms, the animation is moving the direction of the cloud elements across the x axis of the screen. This is something that the transform: translateX() property can do almost copied in exactly in place for the left property. Adding will-change to the cloud rule made it all work together.

This replacement felt easy. However, other animations might not be so easy… So do your homework!

Using these properties comes with some significant benefit:

  • Avoids costly layout and paints on the main thread
  • Avoids some Cumulative Layout Shift

I conquered the clouds, and made it run with translateX and significantly dampened the main thread activity.

A shadow across the land…

The Sun… well it didn’t get the same fast treatment so quickly. That is because it used a non-composited property that so far, as of writing this, I haven’t figured out how to recreate. Opacity may hold the key but I haven’t got it yet.

Check out the stylish CSS sun:

 .sun { width: 175px; height: 175px; background-color: #FFDE00; border-radius: 50%; box-shadow: 0 0 0 20px #FFDE0080, 0 0 0 40px #FFDE0040, 0 0 0 60px #FFDE0020, 0 0 0 80px #FFDE0010, 0 0 0 100px #FFDE0000, 0 0 40px 100px #FFDE0010; animation: sunrise 2s infinite linear forwards, rays 2s 2s infinite linear; } 

However, see the non composited problem in its rays:

 @keyframes rays { 0% { box-shadow: 0 0 0 0 #FFDE0080, 0 0 0 20px #FFDE0080, 0 0 0 40px #FFDE0040, 0 0 0 60px #FFDE0020, 0 0 0 80px #FFDE0010, 0 0 40px 100px #FFDE0010; } 100% { box-shadow: 0 0 0 20px #FFDE0080, 0 0 0 40px #FFDE0040, 0 0 0 60px #FFDE0020, 0 0 0 80px #FFDE0010, 0 0 0 100px #FFDE0000, 0 0 40px 100px #FFDE0010; } } 

Box-shadow is not a compositor-only property. The pulsing rays were cool to see but were coming at a cost – if the website just sat there running the rays using this box-shadow property that was being changed would chip away at the main thread over and over. Maybe you could compare it to UV exposure.

For now, since I did not know how to make this effect with compositor-only properties, I made the sun static and removed the rays animation that used box-shadow. It now has a nice box shadow, it just doesn’t pulse.

Bonus performance tip: animation-iteration-count

I also considered the masters wisdom even now that the clouds were in the compositor… don’t run things infinitely in the background generally speaking. It is better to give it a limited run and now the clouds move only a few times before stopping. If I restarted the sun animation… it would definitely have this. Composited or not.

Conclusion

My website had two animations but only one survived a transformation into fully using the compositor. Can you make a good sunshine animation with opacity? Let me know, I’d love a tip!

I hope this Cloud and Sun story brightens your day and animating interest.

Similar Posts

Loading similar posts...