Habdul Hazeez I teach and write code with interests in web development, computer security, and artificial intelligence.

Best practices for improving CSS performance

6 min read 1846

Best Practices For Improving CSS Performance

Editor’s note: This article was last updated on 20 October 2022 to include information on compressing CSS files and lazy loading in CSS.

CSS sits at the presentation layer of website design. If done right, it adds beauty for your users and the right feel to the HTML markup underneath. If not, it can cause a bad user experience and do a number on your website’s speed and performance.

Irrespective of the nature of your website, and regardless of whether it performs well on a variety of web browsers, it has to load quickly. If it’s not fast, your users will leave and go elsewhere.

If you happen to sell services or goods on your website, this means reduced sales because there are plenty of options available on the web, and you’ve given the user a clear indication to go look elsewhere. They may even discourage others from using your website in the future, which could result in reduced page views.

In this article, you’ll learn how to avoid some common CSS coding decisions that will bog down your website. By the end, you’ll be able to speed up your website and improve the UX.

We’ll cover these eight CSS topics to improve your code and increase the performance of your website:

  1. Write simple selectors
  2. Avoid excessive animations
  3. Know when to animate expensive properties
  4. Avoid the @import statement
  5. Optimize your file sizes
  6. Avoid base64 bitmap images
  7. Compress your CSS
  8. Lazy load your CSS

Why CSS affects site performance

Simply put, CSS affects site rendering. CSS is a part of the critical rendering path of a site, i.e., the minimum amount of information a website needs to render its first pixel. This means that while the CSS is parsing, it’ll block all other resources from loading, including HTML and CSS functionality.

In fact, you probably won’t see a single pixel of a site nor be able to interact with the page while the CSS is parsing, so it’s important that you optimize your CSS for maximum performance. You can do this by following the next eight steps.

1. Write simple selectors

CSS has a wide, flexible array of coding options you can use to target HTML elements for styling. Over the years, experts have advised developers to write simple selectors to reduce the load on the browser and keep the code clean and simple.

This next code block demonstrates what simplicity is all about:

.hero-image {
        width: 70%
}

However, CSS does not stop you from writing the following:

main > div.blog-section + article > * {
        /* Code here */
}

In this example, behind the scenes, the browser will parse the selector from right to left, starting with the universal selector (*) and reading across to the main selector. This is more work for the browser than usual. Even though we’re talking about a difference of milliseconds to parse this selector, those milliseconds add up when this selector method occurs multiple times in your style sheet.

Moreover, the longer your selectors, the more bytes they add to the overall size of your style sheet.

2. Avoid excessive animations

Now that animation is available in native CSS, there’s no need to use JavaScript to add animations to your webpages. This makes adding animations to your website easier and, if done right, you can leverage them to create a better user experience.



When you overdo it with animations, however, you can distract the user from performing the task they are trying to achieve when they visit your website. Also, keep in mind that each animation you add takes time to parse, so excessive animation can slow down or halt the web browser.

3. Know when to animate expensive properties

Properties that cause the whole page to re-layout should not be animated. These properties are typically referred to as being “expensive” because they can create a significant load time on your website. Some of them are:

  • margin
  • padding
  • height
  • width

The reason for this is that when you change properties like margin and other dimensions of a single DOM element, it causes changes to all other elements.

Some other properties, such as opacity and transform, can be animated because they don’t affect the layout of other elements. This makes it possible for web browsers to offload those computations to the GPU to be even faster.

Other CSS properties are more commonly used but will still take longer to paint. Some of them include:

  • :nth-child
  • box-shadow
  • border-radius
  • position: fixed

When these appear in the hundreds in your style sheet, they will impact the performance of your website. Use them sparingly.

4. Avoid the @import statement

The @import statement is mostly used to include assets, such as fonts, though it can include other CSS files.

CSS is render-blocking, which means that when you use the @import statement in your CSS file to fetch a font or other CSS file, the browser will fetch the asset before it continues processing the remaining CSS code:

/* styles.css */
/**
 * The browser would fetch base.css before
 * processing the remaining code in styles.css
 */
@import url("base.css");

When the asset is a font file, the browser will use the font available in the system while it waits for the other font to download. After it downloads, it’ll swap out the system font for the downloaded font. Therefore, your user could be reading your content in one font and suddenly the font changes. This is bad for user experience.

Here is an example of loading a font with the @import statement:

/**
 * Example of loading a font with the
 * @import statement.
 * The font is only available after it downloads.
*/
@import url('https://fonts.googleapis.com/css2?family=Roboto:[email protected]&display=swap');

Instead, we recommend using the link tag in the head of your HTML to load your fonts:

<link rel="preload" as="font" href="https://fonts.googleapis.com/css?family=Open+Sans" crossorigin="anonymous">

Here, the rel="preload" and as="font" tell the browser to download the font as soon as possible. You can also take steps to ensure the font file you are preloading matches the ones in your CSS to prevent your user from downloading two versions of the same font and wasting their bandwidth.


More great articles from LogRocket:


5. Optimize your file sizes

In web design and development, size matters. Whether you’re dealing with an image, an HTML or JavaScript file, or other media assets, there’s one golden rule: always be compressing.

Reduce your CSS file size by minification. Images on your site should be optimized to reduce their load speed, which can mean using an online tool like TinyPNG — or, if you’re creating your own images, leveraging tools such as Save for Web in Photoshop.

6. Avoid base64 bitmap images

Base64 images are among the options for embedding images on a webpage. Over the years, experts such as Harry Roberts have shown why base64 images are bad for performance for many reasons:

  • They significantly increase the overall size of the CSS file
  • They get downloaded regardless of whether they’re used or viewed
  • Base64 encoding results in a larger-than-normal image file size
  • The browser must parse the entire base64 string before it can be used

In the image below, observe the increase in each image’s size before and after conversion to base64:

Before And After Of The Base64 Image Conversion

See what happens when we add these three base64 images to a CSS file with only 14 lines of code:

/**
 * Base64 code truncated.
*/
@media screen and (min-width: 20em) {

    html {
            background-image:  url('data:image/png;base64,iVBO ...');
    }

    footer {
            background-image:  url('data:image/png;base64,iVBO ...');
    }

    .non-existence-class {
            background-image:  url('data:image/png;base64,iVBO ...');
    }

}

The file size increased to over 500KB. Not only is that massive, but the user’s browser will also spend time downloading this file whether or not the image is used:

Base64 Image File Size Increase

Meanwhile, in the following code, the browser would download the image on demand based on the browser’s viewport:

html {
    padding: 2em;
    background-image: url("images/asnim_mobile.jpg");
}

@media screen and (min-width: 20em) {
    html {
            background-image: url("images/asnim_tablet.jpg");
    }
}

@media screen and (min-width: 48em) {
    html {
            background-image: url("images/asnim.jpg");
            background-size: cover;
    }
}

You can verify this by performing the following steps:

  1. Create three differently sized images for different breakpoints, as shown in the previous code block
  2. Replicate the code block with your images as the background images
  3. Launch your browser and open the Network tab in the developer tools
  4. Resize your browser viewport and observe

7. Compress your CSS

Uncompressed CSS files generally take twice as much time to load than compressed CSS files, so compressing your files should be an easy decision — especially if your site has many CSS files.

CSS compressors work by removing white spaces, line breaks, block delimiters, comments, etc. to reduce the size of the application file. They also find and fix any properties that overlap themselves, and look for chances to use CSS shorthand.

While compressing CSS files makes them more browser friendly, the one downside is that it decreases code readability.

Some compressors also allow you to choose between balancing readability and size, so if you’re working with a team or you know others will read your code, you can still compress CSS while keeping your code readable:

Compressing CSS And Keeping Code Readable

While there are many CSS compressors in the market, you have to take time to find the right one for yourself. Take a look at this list to get started.

8. Lazy load your CSS

Lazy loading is a strategy used to improve the performance of websites by blocking the rendering of non-critical resources until they’re needed. Lazy loading CSS is a great way to decrease the critical rendering path of a page by splitting CSS and loading only the required code, while all others, i.e. images, animation, etc., are loaded on demand.

The main targets for lazy loading are images and videos. The easiest way to lazy load images and videos is by adding the loading attribute to the <img> and <iframe> elements and setting it to lazy. This ensures that the images will only load when they come into the viewport:

<img src="myimage.jpg" loading="lazy" alt="..." />
<iframe src="content.html" loading="lazy"></iframe>

For videos, you can use the preload attribute to lazy load a video that doesn’t autoplay:

<video controls preload="none">
  <source src="Fluffydogs.mp4" type="video/mp4">
  A video about fluffy dogs
</video>

Conclusion

When you take the lessons learned in this article and apply them to your future web projects, know that you’ll be contributing to a better web! If you have a website that you feel needs a performance revamp, refactor your code using lessons learned in this article and let us know how it goes in the comments.

Browse some tips on additional CSS and general web performance updates you can make:

Happy coding!

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Habdul Hazeez I teach and write code with interests in web development, computer security, and artificial intelligence.

Leave a Reply