Skip to main content

Command Palette

Search for a command to run...

Web performance: The Dangers of background images

Updated
2 min read
Web performance: The Dangers of background images
T

Just a guy who loves to write code and watch anime.

Dangerous code

Assume, you've code where you get images from a CMS.

These images should be background images that keep changing.

You approach it in a way where you map out the images and set them as background images.

import React from "react";

const BackgroundImages = ({ images }: { images: string[] }) => {
  return (
    <div className="flex">
      {images.map((image, index) => (
        <div
          key={index}
          className="w-32 h-32 bg-cover bg-center"
          style={{ backgroundImage: `url(${image})` }}
        />
      ))}
    </div>
  );
};

export default BackgroundImages;

Now, your code may look different, but this code is just to demonstrate the dangerous code.

Can you already see the problem?

If not, don't worry. We'll dive into how the browser parses HTML and CSS for us to understand this problem.

Browser receives an HTML document

When the browser receives an HTML document, it parses it from top to bottom, building the DOM tree.

If the parser encounters a <script> tag referencing an external script, it stops parsing the HTML document and fetches the script. You don't want this to happen. Solutions like defer and async are there to help. Your default go-to should be using defer for scripts. I'm not here to explain why, that's covered in my previous blog posts. Several of them, actually.

What about <link> tag referencing stylesheets?

When the parser encounters a <link> tag referencing a stylesheet, it requests that file. However, the parsing of the HTML document can continue. A new parser is started. This is the CSS parser. It builds the CSSOM (CSS Object Model) tree.

Why the browser needs the CSSOM tree:

  • Allows browser to efficiently apply styles.

  • JavaScript can access and modify styles via the CSSOM APIs.

  • CSSOM is used in the critical rendering path. Critical rendering path is the sequence of steps the browser goes through to convert HTML, CSS, and JavaScript into pixels on the screen.

When CSS parser encounters external links

What happens when the CSS parser encounters an external link?

It triggers a request and downloads the file. This blocks the CSS parser from continuing.

If you think through this, this "blocking" is a serious issue. It blocks the critical rendering path from completing. Because we need the CSSOM tree to complete the critical rendering path.

The problem with the code

Going back to our code, you should see the problem now.

The fact that we have to request and download the images sequentially is a problem. This blocks the CSS parser from continuing big time.

H
huy le8mo ago

Bro I’m a bit puzzled here—when I tested this, I didn’t see background images loading sequentially or blocking the CSS parser. My understanding is:

The stylesheet is render-blocking, but images in background-image: url(...) don’t block CSS parsing; they’re requested in parallel with prioritization.

Am i missing something?

A

What is the solution to this issue?

11
T

Lol i should have incldued it:

For fonts: self host

For this: use img tag instead and know which one to preload and which one to lazy load