I've used a lot of CSS transitions over the years. Shifting between values in a smooth fashion is pretty easy with a simple one-liner.

transition: background-color 2s;

But what if you have a lot of transitions? What if you have too many transitions? Your browser tries to run them as fast as your monitor's refresh rate allows (60 times per second, or more). This can be pretty taxing.

Recently I ran into this problem transitioning many elements of a large SVG with a bunch of complex shapes. With all the elements transitioning all at once, the page scrolling started to stutter quite noticeably.

Here's how I solved it. Instead of a transition, I used CSS animations, with steps() to effectively "bring down the frame rate" and stop the browser from doing too much work.

@keyframes color-change {
  100% {
    fill: rgb(12, 169, 210);
  }
}

.do-transition {
  animation-name: color-change;
  animation-duration: 5s;
  animation-iteration-count: infinite;
  animation-timing-function: steps(10);
}

Or you can use the shorthand.

.do-transition {
  animation: color-change 5s infinite steps(10);
}

Just add the do-transition class to the element you want to animate. Adjust the animation-duration and the steps() count to get a balance between smoothness and performance.

const polygon = svg.querySelector("polygon");
polygon.classList.add("do-transition");

Here's a little demo with a simple SVG. I've kept the steps() low to make the effect more noticeable.

That's the basic idea anyway. I hope it helps if you run into a similar problem.

(Bonus tip: Use animation-delay to stagger the animations if you have a lot of elements transitioning at once so they don't all paint on the screen at once on each step())

Happy coding! 🚀