Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Debugging Rendering Performance

Hello! Welcome back to our course on mastering Chrome DevTools.

In our last lesson, we delved into the Performance panel's main thread, learning how to spot long tasks and the costly pattern of forced synchronous layouts. These are critical bottlenecks that directly impact how fluid an application feels.

Today, we'll focus on the visual consequences of these and other performance issues, like jank and excessive repaints. You will learn to use a powerful trio of real-time diagnostic tools from the Rendering tab: the FPS meter, Paint Flashing, and Layer Borders. Mastering these will allow you to instantly see where and why your animations and interactions aren't as smooth as they should be, moving beyond the flame chart to get immediate visual feedback.

What is Jank and Why Does it Happen?

Before we jump into the tools, let's establish a clear, technical understanding of "jank." Your screen refreshes at a constant rate, typically 60 times per second (60Hz). To achieve a smooth animation, the browser must produce a new frame to display on every single refresh—that gives it about 16.7 milliseconds to do all its work (JavaScript, style, layout, paint, and composite).

When the browser fails to produce a new frame in time, the screen doesn't get an update. The same frame is shown again, causing a stutter or "jank" in the motion. This breaks the user's sense of direct interaction with the interface.

The following video provides a great introduction to the concept of jank and sets the stage for our investigation into the rendering process.

Google I/O 2013 - Jank Free: Chrome Rendering Performance

Watch this short segment from the classic Google I/O talk, 'Jank Free: Chrome Rendering Performance,' to understand the definition of jank and its relationship to the browser's rendering pipeline.

Watch from the beginning until 03:12. Focus on how jank is defined as a missed frame and how the various stages of rendering (JavaScript, painting, compositing) can contribute to the problem.

As the video explains, the cause of a missed frame can lie in any part of the rendering pipeline. In the last lesson, we looked at long-running JavaScript and forced layouts. Now, we'll focus on tools that give us insight into the paint and composite stages.

The Rendering Pipeline: A Quick Refresher

To effectively diagnose rendering issues, it's essential to understand the sequence of steps the browser takes to turn your HTML, CSS, and JS into pixels on the screen.

  1. Style: The browser calculates the final CSS styles for each element.
  2. Layout: It computes the geometry of each element—its size and position on the page. Changing properties like width, height, or left will trigger this step.
  3. Paint: The browser fills in the pixels for each element on one or more layers. Changing properties like background-color, box-shadow, or color triggers painting.
  4. Composite: The browser draws the various layers to the screen in the correct order. This is the final step.

The key to performant animations is to minimize the work the browser has to do on each frame. Ideally, you want to make changes that only trigger the Composite step, which is handled very efficiently by the GPU.

The following article provides a concise overview of this pipeline and how it relates to animation performance.

Investigate Animation Performance with DevTools

This article, 'Investigate Animation Performance with DevTools,' offers a clear, textual explanation of the browser's rendering steps. It serves as a great reference for the concepts we'll be applying.

Read the sections 'Demystifying rendering' and 'Animation performance'. Pay close attention to the distinction between properties that trigger Layout and Repaints versus those that can be handled by the Compositor (transform and opacity).

Now, let's explore the tools that help us visualize this process in real-time. You can find all of them by opening the Command Menu (Cmd+Shift+P or Ctrl+Shift+P), typing Rendering, and selecting Show Rendering.

Tool 1: The FPS Meter - Quantifying Smoothness

The first step in diagnosing jank is to quantify it. The FPS Meter provides a real-time overlay showing you the current frames per second.

Janky Animation with FPS Meter Display
The FPS meter overlay in the top-right corner, clearly indicating a low frame rate and providing other stats like GPU memory usage. This is your first clue that an animation is janky.

The official documentation provides a quick reference for this feature.

Performance features reference | Chrome DevTools

This section of the Chrome DevTools documentation explains how to enable and interpret the real-time FPS meter.

Read the short section 'View frames per second in real time with the FPS meter'. This will show you exactly where to find and enable this feature in the Rendering tab.

With the FPS meter enabled, perform the animation or interaction you're investigating. If you see the FPS number consistently dip below 60, you've confirmed a performance issue. The next step is to find out why.

Tool 2: Paint Flashing - Seeing What Gets Repainted

A common cause of poor rendering performance is causing the browser to repaint large or complex parts of the screen on every frame. Paint Flashing is an invaluable tool that draws a green overlay on any area of the page that is being repainted.

To see this in action, let's return to the "Jank Free" video, where they demonstrate how seemingly harmless CSS changes can trigger large, unnecessary repaints.

Google I/O 2013 - Jank Free: Chrome Rendering Performance

This segment demonstrates the 'show paint rectangles' feature (now called Paint Flashing). It provides a powerful visual for understanding which parts of your page are being repainted and why.

Watch from 07:54 to 11:08. Notice how adding an element below the fold only repaints the scrollbar, but changing the padding on a container repaints the entire container, even though nothing visually changes. This is a classic example of an excessive repaint.

When you see large green flashes during an animation, especially in areas you don't expect to change, it's a strong signal that you're animating a property that is expensive to paint. For example, animating box-shadow or background-image will trigger paint on every frame. The ideal animation causes no green flashes at all.

Tool 3: Layer Borders - Verifying Your Compositing Strategy

So, if we want to avoid painting, how do we achieve animation? By promoting elements to their own compositor layer. When an element is on its own layer, the browser can move, rotate, scale, or fade it using the GPU, without needing to repaint it or recalculate the layout of other elements. This is why animating transform and opacity is so performant.

The Layer Borders tool draws an orange border around any element that has been promoted to its own compositor layer. This lets you verify that your performance optimization strategy is actually working.

Chrome DevTools: Enabling Layer Borders in the Rendering Tab
The Rendering tab with 'Layer borders' enabled. You can see the orange outlines on the page, confirming which elements are being treated as separate layers.

The "Jank Free" video provides the perfect demonstration of this workflow: identifying a janky animation, fixing it by switching from animating left to transform, and verifying the fix with layer borders.

Google I/O 2013 - Jank Free: Chrome Rendering Performance

This is the most critical part of the lesson. It connects all the concepts: identifying repaints, fixing the code to use a compositable property, and verifying the fix.

Watch from 13:16 to 23:43. First, observe how animating the left property causes constant repaints (18:50 - 21:01). Then, see how switching to transform: translateX() eliminates the repaints and results in a smooth animation. Finally, watch how they use 'Show composited layer borders' to confirm that the element gets its own layer during the transform animation (21:01 - 23:43). The discussion about translate3d forcing layer promotion is a classic and still relevant technique.

Key principle: Use transform for movement/scaling/rotation and opacity for fading. Then, use the Layer Borders tool to confirm that the animated element gets its own layer. If it does, you've likely eliminated paint and layout from your animation loop, leading to a buttery-smooth 60 FPS.

Test your understanding!

You are building a complex dashboard where users can drag and drop widgets. During the drag operation, the UI feels sluggish and the FPS meter drops to around 20-30 FPS. You enable Paint Flashing and see the entire container of widgets flashing green as you drag one of them.

Based on what you've learned, what is the most likely cause of this performance problem, and what CSS property would you use to implement the drag movement to fix it? How would you verify your fix?

Show answer
  1. Likely Cause: The sluggishness and widespread green flashing indicate that the drag-and-drop logic is likely updating the left and top CSS properties of the widget on every mouse movement. This forces the browser to re-calculate the layout and repaint the container on every single frame of the drag, which is extremely expensive.

  2. The Fix: You should change the implementation to update the widget's position using the transform: translate(x, y) property instead of top and left.

  3. Verification:

    • Paint Flashing: After applying the fix, you should see that the green flashes disappear during the drag operation.
    • Layer Borders: To be certain, you would enable Layer Borders. You should see an orange border appear around the widget as soon as you start dragging it, confirming it has been promoted to its own compositor layer. The rest of the UI should not have borders (unless they also have layers for other reasons).
    • FPS Meter: The FPS meter should now stay at or very close to 60 FPS during the drag operation.

Conclusion

In this lesson, we explored the visual and real-time side of rendering performance. By understanding the browser's rendering pipeline, you can make informed decisions about how to write your CSS and JavaScript to achieve smooth animations.

Key Takeaways:

  • Jank is the result of the browser missing a frame, often because a step in the rendering pipeline took too long. The goal is a consistent 60 FPS.
  • The FPS Meter gives you a real-time quantitative measure of your application's smoothness.
  • Paint Flashing visually identifies which parts of the page are being repainted. Your goal for performant animations is to eliminate or minimize these green flashes.
  • Layer Borders allows you to verify that elements are being promoted to their own compositor layer, which is key for avoiding expensive layout and paint operations when animating transform and opacity.

In our next and final lesson for this module, we will shift our focus from runtime performance to load-time performance. You'll learn how to use the Coverage tab to find and eliminate unused CSS and JavaScript, reducing your application's initial bundle size and improving how quickly it becomes interactive.

Can't find a good explanation? Sign up and we'll make it for you

Sign up