Skip to main content

How to Defer Offscreen Images and Background Images

· 26 min read
Anna Monus

Deferring offscreen images is a web performance optimization technique that can help you improve user experience and Core Web Vitals on your site. Also known as lazy loading, it downloads out-of-view images only when they're about to appear in the user's viewport. Deferring offscreen images is especially important on image-heavy websites.

In the past, lazy loading was a complicated process that involved either the manual setup of JavaScript event listeners together with viewport calculations, or the integration of a third-party library. However with the introduction of the loading HTML attribute and the IntersectionObserver browser API, the situation has improved a lot.

Today, we can defer offscreen images right in the HTML using the loading="lazy" attribute, while the IntersectionObserver API provides a performance-friendly way to defer offscreen background images using JavaScript.

What Does 'Defer Offscreen Images' Mean Exactly?

Offscreen images are images that are not visible within the browser viewport, such as content located below the fold, in slide-out panels, dropdown mega menus, image carousels, or other out-of-view locations.

When a user lands on the page, it's still unknown which offscreen images they'll see and which ones they won't, as this depends on individual user behavior. For example, whether they scroll the page down, click through a slider, open the slide-out menu, or perform another action.

As offscreen images are not critical resources, for optimal web performance results, the browser should only start downloading them shortly before they enter the viewport.

Illustration showing examples of on-screen and off-screen images

How Can You Estimate When an Offscreen Image Is About to Enter the Viewport?

You can estimate the appearance of an offscreen image in the viewport by monitoring the user's interactions with the page.

You can use two approaches:

  • The traditional, computationally heavy approach (manual lazy loading):
    • You manually set up event listeners for events related to the change of the viewport's content, such as scroll, change, and resize.
    • This approach is considered computationally heavy because the aforementioned events (e.g. scroll) can fire very frequently while the user is rapidly moving around the screen. As a result, the callback function is executed all the time, which tends to involve lots of DOM manipulations (even if you throttle function execution using the setTimeOut() function, the traditional approach still slows down the page).
  • The modern, lightweight approach (native lazy loading):
    • You use either the loading attribute of the <img> tag in HTML or the IntersectionObserver API in JavaScript to silently observe the user's interactions with the page. The two features are essentially the same thing, as when you use loading="lazy" on the page, the browser instantiates a new IntersectionObserver object using the built-in IntersectionObserver interface.
    • As both features are built into the browser, they can observe the current location of the deferred images without having to manually handle the events, which results in fewer DOM manipulations.

As both loading and IntersectionObserver are supported by all modern browsers, it makes no sense to use the traditional approach anymore — so in this article, we'll only look into the modern, lightweight approach.

How Does Deferring Offscreen Images Improve Web Performance?

Deferring non-critical resources is generally a good idea to improve web performance because critical resources can load faster and the browser can render above-the-fold content sooner. In addition to images, you can also defer other types of resources such as JavaScript and CSS files.

As lazy loading offscreen images and background images speeds up page load time, it can also improve Web Vitals affected by page load time, such as First Contentful Paint (FCP), Largest Contentful Paint (LCP), and Interaction to Next Paint (INP).

Can Deferring Offscreen Images Harm Web Performance?

If you defer offscreen images, there are two important things to pay attention to, as they can hurt web performance and user experience:

  • Don't forget to add the width and height attributes to the <img> element, as lazy loaded images may push other content elements aside if their dimensions are not defined, which can result in unexpected layout shifts and harm your Cumulative Layout Shift (CLS) scores.
  • Don't lazy loading above-the-fold images. Doing so can be especially harmful if you defer images that are candidates for the Largest Contentful Paint element on the page (Lighthouse even has a flag that warns users about not to lazy load the LCP image).

How Do Offscreen Images Load When They Are Not Deferred?

Before moving on to how to defer offscreen images, let's see how images are rendered on the page when they are not lazy loaded.

I created a demo consisting of some flower images displayed in a vertical layout (note that the live version of the demo also includes some text between the images — we'll need this later in the article to run realistic synthetic performance tests).

The screencast video below shows the images and Chrome DevTools' Network tab side by side so that you can see that all images download at initial page load (this is what we'll change using lazy loading):

How Do You Know That You Should Defer Offscreen Images on Your Page?

Web performance analysis tools, such as Lighthouse and DebugBear, show a flag or recommendation when you have offscreen images on the page, and deferring them could improve your Web Vitals and other metrics.

Defer Offscreen Images Lighthouse Audit

Google's Lighthouse tool (you can access it from Chrome DevTools' Lighthouse tab) shows a Defer offscreen images audit together with the potential savings in kilobytes and a list of the offscreen images present on the page:

Defer Offscreen Images audit in Lighthouse

DebugBear's Recommendation

DebugBear's Lazy load offscreen images recommendation is a bit more detailed than Lighthouse's, as it shows the suggestion together with a rendering filmstrip (see in the upper part of the screenshot below) and the request waterfall data of offscreen images (see in the lower part of the screenshot below):

Lazy load offscreen images recommendation in DebugBear

Now, let's see how to defer offscreen images using HTML and then how to defer offscreen background images using CSS and JavaScript.

Lazy Load Images Using HTML

As I mentioned above, lazy loading images used to be a huge hassle. Since the introduction of the native loading attribute, this is not the case anymore.

The loading attribute allows you to define a download strategy for an HTML image or iframe.

You can use it in the following way (don't forget to add the width and height attributes when lazy loading an image to prevent unexpected layout shifts):

<img src="flowers.jpg" alt="Flowers" width="800" height="533" loading="lazy" />

The loading attribute can take two values:

  • eager:
    • The browser sends a download request for the image file to the server when it processes the <img> tag, so it starts downloading almost immediately.
    • This is the default value of the loading attribute.
  • lazy:
    • The browser doesn't send a download request for the image file when it processes the <img> tag but sets up an IntersectionObserverEntry object that will track the intersection state (i.e. relative position) of the lazy loaded image and the viewport.
    • The browser starts downloading the image file shortly before it appears in the viewport (when the image and the viewport start intersecting).
    • If the user doesn't move close to the location of the offscreen image (e.g. doesn't scroll the page down or move the cursor towards a slideout panel), it never downloads.
    • Note that the IntersectionObserver API uses the same technique to defer offscreen images. The advantage of the loading="lazy" attribute is that you don't have to set up DOM objects manually when deferring offscreen images in HTML (it would be nice to have a native background-loading: lazy property in CSS, too, but unfortunately, this is not the case for now).

In addition to the <img> tag, you can also add the loading attribute to <iframe> elements, which can be useful if you want to publish multiple embeds, such as Codepen pens, on your page.

Browser support for the loading attribute is good, as it's supported by all modern browsers, so you can safely use it without providing a fallback method.

To learn more about how loading="lazy" works under the hood, check out our article on the attribute — in addition to the web performance insights, it includes some useful practical tips too (e.g. how to handle lazy loading if you want to enable your users to access your page content when they're offline).

Here, let's go back to our flower demo and see how it changes when we defer the offscreen images.

The code example below shows how to use the loading attribute when there are more images on the page (I didn't add loading="eager" to the first three images, as eager is the default value of the attribute):

<figure>
<img src="images/flowers-01.jpg" alt="Flowers 01" width="800" height="533" />
</figure>
<figure>
<img src="images/flowers-02.jpg" alt="Flowers 02" width="800" height="533" />
</figure>
<figure>
<img src="images/flowers-03.jpg" alt="Flowers 03" width="800" height="533" />
</figure>
<figure>
<img
src="images/flowers-04.jpg"
alt="Flowers 04"
width="800"
height="533"
loading="lazy"
/>
</figure>
<figure>
<img
src="images/flowers-05.jpg"
alt="Flowers 05"
width="800"
height="533"
loading="lazy"
/>
</figure>
<figure>
<img
src="images/flowers-06.jpg"
alt="Flowers 06"
width="800"
height="533"
loading="lazy"
/>
</figure>

To defer offscreen images, you'll need to estimate which images will be visible in the viewport at initial page load. It's important that you don't forget about small-screen devices that are typically used in portrait orientation, so in some cases, more images will be visible within the viewport on mobile than on desktop.

In the screencast video below, you can see that the first five images download immediately, while the other ones only download when the page is scrolled down (see the live version of the demo with deferred images):

You may have noticed that while we added loading="lazy" up from the fourth image, the browser downloaded the first five images at initial page load. This is because the attribute makes some estimates about the intersection of the viewport and the location of the deferred element so that the download process can start some time before the image enters the viewport.

Show Performance-Friendly Placeholders for Deferred Images

Now let's see how to add performance-friendly placeholders to offscreen images. This is important because users on slower devices or networks still need some kind of visual feedback until the images are rendered to the screen.

There are different strategies for providing placeholders for images that have not downloaded yet. For example, there are JavaScript libraries you can use to show the lo-fi versions of full-size images, such as SQIP and LQIP Modern. As these tools generate super lightweight lo-fi images, they're worth considering if you want to provide more visually appealing placeholders for your images.

However, as they still add some overhead to the page, let's see how you can add properly sized placeholders to your images using a simple CSS background color (see above for the HTML):

figure {
display: flex;
justify-content: center;
}
img {
max-width: 100%;
height: auto;
background-color: #d6d6d6;
}

The above code turns the <figure> elements into flex containers, each of which holds one <img> element.

As a result, <img> becomes a flex item, which means that it'll keep its intrinsic size (defined by the width and height attributes in the HTML) when the image file is not available and the placeholder (i.e. the background color) is shown. In other words, the gray placeholder boxes will be displayed in the same size as the corresponding images that will download subsequently.

(The justify-content property is just added for styling, you can remove it if you don't want to center the images within the flex container.)

The max-width: 100% and height: auto declarations make the <img> elements responsive so that they won't be wider than the viewport on small-screen devices.

Image placeholders

Lazy Load Background Images Using JavaScript

While the loading attribute works great for HTML images, you can't use it to defer offscreen background images.

The most performance-friendly way to lazy load background images is the aforementioned IntersectionObserver API. As it belongs to the global Window object, you can access the interface directly, without having to call it from an HTML element present on the page.

To see how to defer offscreen background images using the IntersectionObserver API in practice, we'll use another flower demo that includes the same images as the previous demo, just now they are added as background images to the CSS. The background images are lazy loaded up from the fourth image here too.

Below, you can see how the resources, including the deferred background images, download from the network in the Chrome browser. The first two images are preloaded, that's why they download before the CSS and JavaScript files (note that the live version of the demo inlines the script to make our performance test later in the article more comparable):

HTML: Add a Class to the Offscreen Elements

To defer offscreen background images, you can use the following HTML:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Defer Offscreen Background Images</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="preload"
href="images/flowers-01.jpg"
as="image"
fetchpriority="high"
/>
<link
rel="preload"
href="images/flowers-02.jpg"
as="image"
fetchpriority="high"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="bg-1"><p>CTA Area 01</p></div>
<div class="bg-2"><p>CTA Area 02</p></div>
<div class="bg-3"><p>CTA Area 03</p></div>
<div class="bg-4 deferred"><p>CTA Area 04</p></div>
<div class="bg-5 deferred"><p>CTA Area 05</p></div>
<div class="bg-6 deferred"><p>CTA Area 06</p></div>
<div class="bg-7 deferred"><p>CTA Area 07</p></div>
<div class="bg-8 deferred"><p>CTA Area 08</p></div>
<div class="bg-9 deferred"><p>CTA Area 09</p></div>
<script src="script.js"></script>
</body>
</html>

The code above adds the deferred class to the offscreen <div> elements so that we can lazy load the belonging background images in the following way:

  1. We'll show a simple gray background color for the deferred elements using CSS.
  2. We'll monitor the current positions of the deferred elements using the IntersectionObserver API in JavaScript.
  3. When an observed <div> gets close to the viewport (as the user is scrolling down the page), we'll remove the deferred class from the HTML using JavaScript.
  4. When the deferred class is removed, the CSS will swap the gray background color with the background image automatically.

The HTML also preloads the first two images using the <link> element and sets fetchpriority to high. First, I hadn't thought about this, but DebugBear warned me that the LCP image should be preloaded with high priority when I tested the first version of the demo.

As in this demo, either the first or the second image is reported as the LCP element, I decided to preloaded both (however, note that too many preloads may backfire, so be careful when using this feature):

Request waterfall showing the preloaded background images

CSS: Override the Background Images with a Background Color while the Elements Are Deferred

The CSS below uses a very straightforward technique to swap the background color with the background image when JavaScript removes the deferred class from the HTML — the cascade (CSS stands for Cascading Style Sheets as the cascade is its most fundamental feature):

div {
max-width: 90vw;
margin: 1.25rem auto;
aspect-ratio: 800 / 533;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-1 {
background: #d6d6d6 url("images/flowers-01.jpg") no-repeat;
}
.bg-2 {
background: #d6d6d6 url("images/flowers-02.jpg") no-repeat;
}
.bg-3 {
background: #d6d6d6 url("images/flowers-03.jpg") no-repeat;
}
.bg-4 {
background: #d6d6d6 url("images/flowers-04.jpg") no-repeat;
}
.bg-5 {
background: #d6d6d6 url("images/flowers-05.jpg") no-repeat;
}
.bg-6 {
background: #d6d6d6 url("images/flowers-06.jpg") no-repeat;
}
/* ... */
.deferred {
background-image: none;
}

The code above first defines the backgrounds for the individual <div> elements (.bg-1 , .bg-2, etc.) using the shorthand background property, which:

  • first adds a light gray background color (#d6d6d6), which will serve as the placeholder
  • then specifies the location of the background image (url(...))
  • finally prevents the repetition of the background image (no-repeat)

Then, it adds the .deferred class below the individual elements to take leverage of the cascade in the following way:

  1. The background-image: none rule will apply to the .deferred divs because it's located below the background image rules defined in the shorthand background properties of the .bg-1, .bg-2, etc. declarations, so it will override them.
  2. The background color (#d6d6d6) defined in the shorthand background properties will still apply to the .deferred divs, as the CSS doesn't specify a separate background-color property for them.
  3. When the .deferred class gets removed from the HTML, the background-image: none rule won't apply to the previously deferred divs anymore, so the background images defined for the individual elements in the shorthand background properties will start downloading from the network and then appear on the screen.

The code above also adds the aspect-ratio property to the div elements (it's equal to the ratio of the intrinsic width and height of the image files) so that they'll have the same dimensions as the background images.

Note that without defining the aspect-ratio, the containers won't be the same size as the background images — see an example in the screenshot below (which is OK, if this is the design you want to achieve):

something

JavaScript: Observe the Intersection State of the Deferred Elements and the Viewport

In the JavaScript code, we'll listen to the DOMContentLoaded event which fires when the HTML page is completely parsed and the DOM is ready to use:

document.addEventListener("DOMContentLoaded", () => {
// selects and stores the deferred elements
const deferredElements = document.querySelectorAll(".deferred");

// creates the observer
const elementObserver = new IntersectionObserver(
(entries, observer) =>
// callback function
{
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.remove("deferred");
observer.unobserve(entry.target);
}
});
},

// properties of the observer
{
root: null,
rootMargin: "200px 0px",
threshold: 0,
}
);

// starts observing the deferred elements
deferredElements.forEach((element) => elementObserver.observe(element));
});

After setting up the DOMContentLoaded event listener, the above script selects all elements with the deferred class and adds them to the deferredElements constant (which is a NodeList object that will include all the deferred div elements).

Next, it sets up an IntersectionObserver() object and assigns it to the elementObserver constant, which will be created when the DOMContentLoaded event fires.

As IntersectionObserver is supported by all modern browsers, you can use it without providing a fallback method in JavaScript (later we'll add a CSS fallback for users who have JavaScript disabled in their browsers).

The script also defines three properties for elementObserver:

  • root:
    • It specifies the element against which the positions of the observed elements will be compared.
    • The value null sets the viewport as the root element (this is also its default value).
  • rootMargin:
    • It creates a margin around the root element (here, the viewport) so that the observation can start before it intersects with the observed element.
    • It's a shorthand that works similar to the margin CSS property.
    • The code above sets it to 200px 0px, which creates a 200px margin at the top and bottom of the viewport, so the deferred images will start downloading 200px before they enter the viewport.
    • You can also use a different value if you want to start the download process sooner or later (e.g. 500px will start it sooner).
  • threshold:
    • It specifies the intersection threshold when the callback function will be executed.
    • The value 0 means that it starts executing immediately when an observed div enters the visibility zone (which is the root extended with the rootMargin).
    • Otherwise, threshold must be a decimal value between 0 and 1 (e.g. 0.1 would mean that the callback function is executed when an observed element has reached the 10% of the visibility zone).

The elementObserver object starts observing the deferred div elements stored in the deferredElements constant when the DOMContentLoaded event fires — this functionality is set up in the forEach() loop at the end of the script.

What Does the Callback Function Do?

Whenever a deferred element's visibility state changes (i.e. when it intersects with the visibility area of the root element), the elementObserver object:

  1. creates a new IntersectionObserverEntry object (called entry in the code above)
  2. adds the new entry to the entries array
  3. executes the callback function
info

Since IntersectionObserver is a native browser API, we don't have to initiate the IntersectionObserverEntry objects manually, as the browser handles this task under the hood.

The callback function runs a forEach() loop on the entries array and checks whether each entry in the array is intersecting with the visibility area of root (which happens when the isIntersecting property of the entry is true).

If so, it removes the deferred class of the belonging div from the HTML and instructs elementObserver to stop observing the element.

Add a CSS Fallback for Users Who Have JavaScript Disabled

To support users who have JavaScript disabled in their browsers, you can add the following line of code below the <link rel="stylesheet" href="style.css"> tag in the <head> section of the HTML page:

<noscript
><style>
.bg-4 {
background-image: url(images/flowers-04.jpg);
}
.bg-5 {
background-image: url(images/flowers-05.jpg);
}
.bg-6 {
background-image: url(images/flowers-06.jpg);
}
.bg-7 {
background-image: url(images/flowers-07.jpg);
}
.bg-8 {
background-image: url(images/flowers-08.jpg);
}
.bg-9 {
background-image: url(images/flowers-09.jpg);
}
</style></noscript
>

The code above overrides the background-image rules of the CSS file when the <noscript> tag is active (which happens when JavaScript is disabled in the user's browser), and downloads and displays the background images for non-JavaScript users who otherwise would just see the gray placeholder boxes in place of the deferred background images.

Results of Our Performance Tests

Finally, let's see how our lazy loaded demos performed for the most important metrics on our web performance tests. To make the tests more realistic, I tweaked the demos a bit and added some text between the images, which better represents a real-world website.

I ran automated lab (a.k.a. synthetic) tests every four hours over the course of nine days from DebugBear's US East data center, which is one of our 20+ remote test locations. This means 54 (i.e. 6 * 9) tests per demo.

Below, I'll show the time series comparison charts along with an example of a rendering filmstrip comparison, all created with DebugBear.

1. Desktop Results for the Deferred HTML Images

On the time series comparison charts below, you can see the desktop scores for four key performance metrics:

The blue line shows the non-deferred, while the green line shows the deferred version of the HTML demo on desktop (which defers offscreen images using the loading="lazy" attribute):

Time series comparison for the HTML demos on desktop

According to the time series data above:

  • The page weight was significantly lower for the lazy loaded version because the browser didn't have to download the deferred images from the network.
  • FCP and LCP were consistently lower for the lazy loaded version throughout the nine test days.
  • Lighthouse's Performance scores were about the same for the two demos. Since this metric depends on multiple factors, it's not surprising that the difference stemming from deferring offscreen images didn't change it in a significant way.

Below, you can see the rendering filmstrip comparison from the last automated lab tests DebugBear ran for the non-deferred and deferred HTML demos on desktop, which shows the nominal values of the performance metrics (e.g. the desktop LCP score improved from 641 milliseconds to 574 milliseconds):

Rendering filmstrip comparison for the HTML demos on desktop

2. Mobile Results for the Deferred HTML Images

Now, let's see how the same HTML demos performed on the series of automated mobile lab tests I ran with DebugBear throughout nine days:

Time series comparison for the HTML demos on mobile

As you can see above, the mobile results are very similar to the desktop ones:

  • The page weight significantly shrank when the offscreen images were deferred.
  • FCP was a bit lower for the lazy loaded version.
  • LCP was significantly lower for the lazy loaded version, and the difference stayed consistent throughout the testing period.
  • Lighthouse's Performance scores were about the same.

Below is the rendering filmstrip comparison from the last automated mobile lab tests I ran — as you can see, the mobile Largest Contentful Paint score significantly improved when the images were deferred (from 2.24 seconds to 1.73 seconds):

Rendering filmstrip comparison for the HTML demos on mobile

3. Desktop Results for the Deferred Background Images

Now, let's see the results of DebugBear's automated lab tests for the non-deferred vs deferred version of the background image demo on desktop:

Time series comparison for the JavaScript demos on desktop

As the time series data above shows:

  • The page weight was significantly lower for the lazy loaded version (for the aforementioned reason, i.e. the browser didn't have to download the deferred background images).
  • FCP and LCP were consistently lower for the lazy loaded demo, however for LCP, the difference was smaller than for the HTML demos on desktop, as here, the page structure was more complicated (the background images were added by CSS and JavaScript).
  • Lighthouse's Performance scores were about the same here, too.

Below, you can also see the rendering filmstrip comparison for the last test run — the desktop LCP score still improved a bit (from 633 milliseconds to 618 milliseconds):

Rendering filmstrip comparison for the JavaScript demos on desktop

4. Mobile Results for the Deferred Background Images

Finally, let's see how the background image demos performed on mobile throughout the testing period:

Time series comparison for the JavaScript demos on mobile

As the time series comparisons above show:

  • The page weight was significantly lower for the deferred version of the demo.
  • FCP was somewhat lower for the lazy loaded version, and the improvement remained consistent throughout the testing period.
  • The LCP values for the two demos were similar overall — sometimes the deferred version performed slightly better while sometimes the non-deferred one did. However on the last day, the deferred demo had a significantly lower LCP score, which shows that lazy loading background images with JavaScript sometimes can still have positive outcomes on mobile devices.
  • As before, there was no significant difference between Lighthouse's Performance scores for the non-deferred and deferred versions of the demo.

In the screenshot below, you can see the rendering filmstrip comparison for the last test run, too — the mobile LCP score significantly improved (from 2.40 seconds to 1.76 seconds) when the background images were deferred (however, note that this test run was an exception throughout the testing period, and the LCP results of the two demos were typically close to each other):

Rendering filmstrip comparison for the JavaScript demos on mobile

Test How Much You Can Improve Your Web Vitals by Deferring Offscreen Images

If you want to test whether it's worth deferring offscreen images on your page before you change the code on your live site, you can use DebugBear's Auto Experiment feature.

It allows you to run pre-configured experiments for DebugBear's web performance recommendations, such as Lazy Load Offscreen Images, and then compare the performance results of the live page and the experiment.

To use the feature, scroll down to the Recommendations section on the test results page, find the recommendation you want to improve, and click the Run Experiment button:

Run experiment button on the test results page of a DebugBear lab test

On the next screen, you'll see the code changes that will be used in the Auto Experiment, e.g. here, DebugBear will add the loading="lazy" attributes to the <img> tags belonging to the deferred images on the page.

If you want to change anything in the auto-generated code, you can edit the HTML document manually. DebugBear may also recommend related page speed improvements that you can add to your experiment (e.g. Preload LCP image with high priority in the screenshot below).

You can run the auto experiment multiple times to reduce variability, too (the default setting is 3, meaning that the lab test will run three times and DebugBear will show the median value of the three tests).

If you don't want to modify the auto-generated code improvement, set a value for the Run test multiple times field, and then click the Run Experiment button:

Page Speed Experiments configuration in DebugBear

You may need to wait a few minutes for DebugBear to run the tests. On the test results page, you'll see the performance scores for the live page (Baseline) and the median value of the auto experiments (Experiment) side by side.

Note that as these are synthetic tests, you can also run auto experiments for any other sites, e.g. your competitor's home page, not just for your own domains.

As the screenshot below shows, DebugBear's Lazy load offscreen images auto experiment improved all the performance metrics (even Lighthouse's Performance score grew from 97% to 100%), meaning that the technique is worth implementing on the live page:

Results of the auto experiment

Wrapping Up and Further Resources

Deferring offscreen images and background images offers significant web performance benefits on both desktop and mobile devices. It enhances the user experience, reduces the page weight, and improves Web Vitals such as First Contentful Paint and Largest Contentful Paint.

In addition to deferring offscreen images, there are other ways to optimize your images for performance, such as using responsive images and next-gen image formats. You can combine those web performance optimization techniques with lazy loading to improve image performance even more.

The most important thing, however, is to detect the potential web performance issues of your own images because every website and application is different, and you may always come across surprising findings you haven't thought about before.

Besides setting up synthetic lab tests where you control the test conditions (e.g. device type, location, etc.), you can use real user monitoring (RUM) to see how your pages perform for metrics that can only be accurately measured on real website visitors, such as Interaction to Next Paint and Cumulative Layout Shift.

With DebugBear, you can start catching and solving your web performance issues for free. To do so, run a free speed test on your most important pages or sign up for our 14-day free trial (no credit card required) to take leverage of all the debugging and monitoring features, including synthetic testing, RUM, detailed Core Web Vitals analysis, long-term CrUX comparisons, and more.

Website monitoring illustration

Monitor Page Speed & Core Web Vitals

DebugBear monitoring includes:

  • In-depth Page Speed Reports
  • Automated Recommendations
  • Real User Analytics Data

Get a monthly email with page speed tips