Our app was mysteriously using 60% CPU and 25% GPU on my M2 MacBook. It turned out this was due to a tiny CSS animation! In this post, I show how to find expensive animations, why some are so expensive, and how to make many animations much cheaper. Along the way, we'll learn how the browser renders CSS animations and how to use Chrome's dev tools for performance profiling. The problem While building Granola, a note-taking app, I noticed it was using 60% CPU and 25% GPU on my M2 MacBook: Activity Monitor showing high CPU and GPU usage What is Granola spending those cycles on? It's an Electron app, so let's use the Chrome dev tools to find out! First, in the "Performance" tab, we see that most of the time is spent not in JavaScript, but in "rendering" and "painting": But what is it rendering and painting? To see this, open the "Layers" tab, which shows: Our window has two layers: one for the "action bar" at the bottom, and another for the rest of the document content. Each layer has a "paint count", and the action bar's layer is painting every single frame! Paint flashing (green) and layout shift regions (blue). Dev tools warns that these animations "may not be suitable for people prone to photosensitive epilepsy." Why is the action bar painting so much? For a clue, jump to the "Rendering" tab, and turn on "paint flashing" and "layout shift regions". We quickly see the browser hates our audio volume visualizer! Those three green "dancing bars" at the bottom of the Granola window constantly flash with layout shift and repainting. But why are the dancing bars causing so much layout calculation? My first suspicion was DOM updates: the bars' styles update 10 times per second, and DOM updates are expensive, right? But reducing DOM updates made little difference. Back to the Performance tab, and we see this pattern dominating the profile: That stuff happens once for every frame, 60 times per second. No JavaScript here — this is pure CSS work! Why is it doing work every fram...
First seen: 2025-07-22 17:51
Last seen: 2025-07-23 13:54