search ]

Improve Frontend, Animations & Scrolling Performance

Whether you’ve noticed it or not, in recent years, the topic of optimization and performance of websites has become a hot topic. It primarily focuses on the loading time of websites and is achieved by reducing the overall weight of files, server-level optimization, and other techniques.

But what about optimization after the page has loaded? In the past, there were no suitable tools for analyzing Frontend Performance, and the need for them was not obvious.

The way we access the internet has changed drastically, and a very large percentage of the population browses the web on mobile devices. Although the hardware of mobile devices has improved over the years, mobile devices are still significantly less powerful than desktops and laptops, which means your website’s performance on those devices is lower and may frustrate users – or worse, cause them to abandon the site entirely.

As the websites we develop become more complex, we need to ensure a proper user experience through optimization of animations and scrolling performance (Scrolling Performance) among other things.

To do this, we need to achieve a frame rate of 60fps, a number that matches the refresh rate of most screens, to provide as smooth an experience as possible.

On mobile devices, and sometimes even on laptops and desktops, providing that level of performance can be challenging, especially on complex sites. In this article, I’ll explain how to approach this issue on your site and improve Frontend performance.

This topic is broad and there’s a lot to say about it, but I’ll try to maintain focus in this guide and explain in a straightforward way one method to improve Frontend performance with an emphasis on scrolling performance.

About Frontend Performance and the Repainting Action in Browsers

If you’re changing the layout – i.e., changing the position of elements on the page – then the browser is forced to repaint the pixels on the screen, an action called repainting.

A repaint occurs with any attribute change to an element on the page that isn’t a change in opacity or transform. When the browser changes layout, it will always perform a repaint because every geometric change of an element means pixels need to change.

In most cases, “arranging” the pixels on your screen is the most time-consuming action in the rendering pipeline and should be avoided as much as possible.

If we use the images that Google provided, the work the browser performs (the pipeline we’re talking about) goes like this:

Browser rendering pipeline - triggering layout and paint

By the way, there are situations where we change non-geometric attributes such as backgrounds, text color, shadows, and so on. In those cases, there is no need for the layout step, and the pipeline will look like this:

Browser rendering pipeline without layout step

Using Chrome Dev Tools to Identify Repainting Bottlenecks

You can use Chrome Developer Tools to quickly identify areas that are repainted on your site. Go to the developer tools and open the Rendering tab. Then enable the “Paint flashing” option as shown in the following image:

Paint Flashing option in Chrome Dev Tools Rendering tab

When this option is enabled, Chrome will flash green over areas that are being repainted. Scroll through your site with this option on, and you’ll likely discover several elements that are repainted during scrolling even though, at first glance, it’s not clear why.

If you find such areas, you’ll need to investigate and check why they are being repainted repeatedly.

Let’s look at an example to better understand. Here is a video showing which areas were repainted when I scrolled through Savvy Blog (this is no longer the case after optimization):

Notice several things during the scroll:

  • The top part of the page (header) is painted green.
  • The share buttons on the right are painted green.
  • The box with another article (at the bottom of the page on the left) is painted green.

All these parts are repainted and load the browser every time a user scrolls. What do these three have in common? They all have position: fixed.

If you encounter situations where scrolling is not smooth and there are “stutters” during scrolling, it is likely that the repainting action in those sites is heavy. As we noted, this could be caused by fixed elements, various animations, and the like.

Of course, we don’t want to change the design of our site because of these stutters, so let’s see how to fix them to create smoother scrolling.

Let’s see how we can avoid potential scrolling and animation problems by creating new layers for certain elements.

The idea is to reach a state where the site operates at 60FPS. The lower the frames per second, the higher the chance you will experience stutters in animations and scrolling.

Creating New Layers for Those Elements

There is no requirement for the browser to treat what we see on the screen as a single image in memory.

In fact, you can cause the browser to treat different elements as a separate layer – in other words, as a number of separate images. You can create a separate layer for certain elements, making them independent and not dependent on other elements on the page.

Think about it: when a certain element is position: fixed and we are looking at a single layer containing all elements including that fixed element, the browser has to repaint the single layer every time because the position of that element is different each time relative to the other elements on the page.

Fortunately, the browser already knows how to perform optimization for these situations, but sometimes it needs a little help.

So, as we noted, you can prevent the repainting action from taking place every time by having certain elements in a separate layer instead of treating all elements as a single image. This action is called layer promotion.

Layer Promotion - separating elements into individual browser layers

The advantage of this approach is that elements that are repainted, or those that move on the screen using CSS transforms, can be managed without affecting other elements on the page. The idea is very similar to how Photoshop works – individual layers are managed one above the other to create the final image.

The will-change Property

The best way to create a new layer for a particular element is to use the will-change property in CSS. The will-change property provides a hint to the browser about changes that may occur to a particular element, so the browser can perform optimization for that element before it actually changes on the screen.

This property is supported in all modern browsers and has been classified as “Baseline Widely Available” since 2022. When you give it the value transform, a new layer will be created for that element.

.moving-element {
  will-change: transform;
}

Be aware that will-change with certain values (like opacity or transform) creates a new stacking context, which can affect how elements overlap visually. If z-index suddenly behaves differently after adding will-change, this is probably why.

For older browsers that don’t support will-change, you can use a hack that has existed for years – the translateZ(0) trick:

.moving-element {
  transform: translateZ(0);
}

But pay attention to a few points about will-change before you rush to use it:

  • Do not add will-change to too many elements. The browser tries to perform optimization on its own, and excessive use of this property can lead to high memory consumption and even slow down the page.
  • Adding the property in CSS causes the browser to keep the optimization in memory long beyond what is really necessary. It is preferable to use JavaScript to add the property just before the element changes and remove it after completion.
  • Do not use will-change just because you think there might be performance problems. Use this property only when you are experiencing actual performance issues, and as a last resort.

Let’s see the result on Savvy Blog after I used will-change for those problematic elements we mentioned:

As you can see, all those green squares disappeared because those elements received a new layer and no longer “interfere” with other elements on the screen.

How to Add will-change Using JavaScript

For the purpose of this article, I added will-change using CSS on Savvy Blog. But as I mentioned, it is preferable to toggle this property using JavaScript right before the change is made and to remove it afterward.

Here is an example describing how to do this for a particular element:

var el = document.getElementById('element');

// Set will-change when the element is hovered
el.addEventListener('mouseenter', hintBrowser);
el.addEventListener('animationEnd', removeHint);

function hintBrowser() {
  // The optimizable properties that are going to change
  // in the animation's keyframes block
  this.style.willChange = 'transform, opacity';
}

function removeHint() {
  this.style.willChange = 'auto';
}

The content-visibility Property

Another modern CSS property worth knowing about is content-visibility. While will-change optimizes elements that animate, content-visibility: auto tells the browser to skip rendering work (layout and painting) for elements that are off-screen entirely.

This is especially useful for long pages with heavy content below the fold. The browser defers the rendering of those sections until the user scrolls to them, which can dramatically reduce the initial rendering cost.

.below-the-fold-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}

The contain-intrinsic-size property gives the browser an estimated size for the element so that scrollbar calculations remain accurate even before the content is rendered. As of 2025, content-visibility is supported in Chrome, Edge, Firefox (125+), and Safari (18+).

Tips for Better Frontend Performance

There are several things you can do to improve scrolling and animation performance on your site. These changes mean the CPU/GPU won’t have to work as hard, which also translates to happier visitors and lower battery consumption on mobile devices.

  • Avoid background images with background-attachment: fixed. In certain browsers, these cause repainting during scrolling and poor performance.
  • If you are using sliders or animations on your site, make sure you create a separate layer for them using the will-change CSS property.
  • If there are many CSS effects – for example, many rounded corners, linear-gradient values, and shadows – consider reducing their use. There’s no problem using them, but if they exist excessively on your site, it will have an impact on Frontend performance.
  • Always use the exact image size that the browser needs to display. If you work with WordPress, take a look at the guide I wrote about creating image sizes on these sites.
  • For JavaScript-driven animations, use requestAnimationFrame to synchronize with the browser’s refresh cycle. This ensures your animation code runs at the optimal time and avoids unnecessary frame drops.
  • Stick to animating only transform and opacity properties whenever possible. These are the only properties that can be handled by the browser’s compositor thread without triggering layout or paint. Animating properties like width, height, top, or left is significantly more expensive.

FAQs

Common questions about frontend performance and scrolling optimization:

What causes janky scrolling on websites?
Janky scrolling is typically caused by heavy repainting. Elements with position: fixed, complex CSS effects, large background images with background-attachment: fixed, and JavaScript-heavy scroll handlers can all trigger expensive repaints that drop the frame rate below 60fps.
What is layer promotion and when should I use it?
Layer promotion means moving an element to its own compositor layer so that it can be painted and animated independently from the rest of the page. Use it when a position: fixed element or a frequently animated element causes visible repaints. The easiest way is to apply will-change: transform to that element.
Can I add will-change to every element on my page?
No. Adding will-change to too many elements is counterproductive. Each promoted layer consumes GPU memory, and the overhead of managing many layers can actually make performance worse. Only apply it to elements that are causing measurable performance issues.
What is the difference between will-change: transform and transform: translateZ(0)?
Both promote an element to its own layer. transform: translateZ(0) is an older hack that forces a 3D transform context. will-change: transform is the standards-based approach that signals intent to the browser without actually applying a transform. Use will-change in modern browsers and fall back to translateZ(0) only if you need to support very old browsers.
Which CSS properties are cheapest to animate?
The cheapest properties to animate are transform and opacity. These can be composited on the GPU without triggering layout or paint. Animating any other property - such as width, height, top, left, or margin - triggers layout recalculations, which are significantly more expensive.
How does content-visibility: auto help with performance?
The content-visibility: auto property tells the browser to skip rendering (layout and paint) for elements that are off-screen. This can dramatically reduce the initial rendering cost of long pages. The browser will render those sections only when the user scrolls to them.

Summary

Chrome’s developer tools provide many ways to analyze and discover performance issues on your site, whether it’s Frontend performance or loading time performance.

Creating a separate layer for certain elements is the right action to take if you are experiencing performance problems in animations and scrolling. The will-change property is an excellent solution, especially on complex sites – don’t be afraid to use it when necessary. At the same time, be careful not to overuse it.

For broader CSS performance optimization, consider auditing your stylesheets for expensive properties and excessive effects.

And if we’re talking about scrolling, take a look at the post I wrote about CSS driven scroll animations using AOS.

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo