Made in Builder.io

Announcing Visual Copilot - Figma to live in half the time

Builder.io logo
Talk to Us
Platform
Developers
Talk to Us

Blog

Home

Resources

Blog

Forum

Github

Login

Signup

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

‹ Back to blog

The Complete Guide to Optimizing CSS for Fast Page Loads

April 18, 2022

Written By Steve Sewell

A comprehensive list of solutions to help you optimize CSS on your website.

Cascading style sheets, or CSS, are essential if you want to build an engaging, and beautiful website. Even the most boring HTML pages become dynamic with CSS. But if your interesting content takes several minutes to load, your users are not going to wait. Let's break down why optimizing CSS is important, and how to go about it using manual hacks and automated tools.


How unoptimized CSS inhibits user experience

CSS might not be the most obvious answer when you set out to optimize your website's code and increase your website's performance. Image optimization is usually the first step, because large, unoptimized images are the lowest hanging fruit. Optimizing JavaScript is the logical next solution that could make your website load faster. 

But when left unoptimized, CSS can have just the same negative impact on performance as images and JavaScript in slowing your site down. Slow websites reduce conversions and harm user experience.


How CSS works (and why it needs to be optimized)

CSS blocks render. CSS impacts the appearance of everything on your website, including fonts and page layouts. This means, your browser will prioritize your CSS in order to paint the page. So if CSS is incorrectly or not at all optimized, your users will either get a slow-loading web page, a page with large portions of it missing, or a completely blank page. 

CSS files grow. Since any part of the code can affect key style choices on the website, developers usually tend to retain everything. Plus, it's generally difficult to find styles that are no longer in use. This means, even with changes, redundant and old code still remains. This includes page styles, components, widgets, etc., that are no longer required. Eventually, the file reaches a point at which its size and complexity intimidate even the most seasoned developers, and maintaining it becomes a huge, challenging project that never gets done.

Large CSS files delay website display. Large stylesheets take longer to be downloaded and processed, blocking the browser and JavaScript APIs from displaying your page. 

Linked CSS files block processing. Stylesheets can reference other stylesheets and assets like fonts and images. This means, the processing of one stylesheet can be interrupted to load other stylesheets, further slowing down the website.  

CSS hinders interactivity. Since CSS is prioritized when loading a page, it stops the parsing of HTML while being processed. This means the longer it takes for the CSS to parse, the longer other critical resources like JavaScript functionality take to load. This increases the time to interactivity, meaning the user cannot interact until all the CSS components are fully displayed.


Best practices for optimizing CSS

The first step is finding out if your website's CSS needs to be optimized. Builder.io's Performance Insights tool is a highly reliable way to find out if there are any opportunities to fix your CSS and speed up your site. Here are some tried-and-tested best practices that most experienced developers swear by.


Reducing CSS file size

As I said before, large CSS files contribute to slow websites and poor user experience. Here are a few ways to tackle large CSS files. 


Removing unused CSS

Optimizing your CSS requires you to have a system in place. Your CSS files need to be named in a way that helps you identify the discrete components that are used on every page. For example, when a file is named "carousel" you can easily tell what that file's responsibilities are. This is also the opportunity to get rid of unnecessary fonts, images, etc. Once you've identified these components, it's easy to keep the ones that are still in use and discard the rest. Once you've removed unused CSS, it's also important to critically consider whether it's absolutely necessary when you build new modules. 


Concatenating, minifying, and compressing CS

Once you've removed all the unused CSS, the next step is to reduce the size of the existing CSS files. You can concatenate them into one file and send out a minified or compressed version of it to boost performance. This reduces the number of HTTP requests a browser needs to make to display the page and is especially important for older browsers.


Prioritizing critical CSS

If you load all the CSS for every visitor on every page, that will significantly slow your website down. On the other hand, if you don't properly load all the render-critical CSS, the user will only see a blank page. 

Striking the perfect balance for optimal user experience involves loading only the critical CSS that is needed for the page to be painted. This involves identifying render-critical CSS components and making sure those go out first. An example of critical CSS might be the background color of the page or key information that a user needs when they visit the page.

There are a couple of recommended methods to handle this.


Inlining critical CSS

One way to make sure that critical CSS gets processed faster is to inline it in HTML. HTML displays the meaningful content on the page while the CSS acts as the decorative component and makes the HTML content dynamic. The goal is to parse the CSS simultaneously or immediately after the parsing of HTML so that the page is rendered, interactive, and functional. Including the critical CSS inline eliminates the step of loading separate CSS files and drastically reduces load time. However, it's important to know that inlining CSS increases HTML file size dramatically, which would almost impact the page load time if not done correctly.


Avoiding @import

Using the @import rule in CSS lets you import an external CSS file in a CSS script. At first glance, this might seem like an effective way to load smaller components and fonts. However, this blocks render and reduces web page speed by loading every imported external file separately instead of loading it in parallel with all the other files needed to render the particular page. It also creates unnecessary HTTP requests. Instead, you can rely on multiple <link> tags within HTML, which is more efficient and loads CSS files in parallel.


Lazy loading CSS as required

Large code files that take a long time to download and parse slow down the browser. Just as in JavaScript, you can solve this problem with code splitting: splitting the code into separate bundles, and dynamically loading only when you need it. With the critical CSS for the content above the fold styled and rendered, the rest of the CSS can be loaded asynchronously so that it doesn't block page rendering. For example, the remaining rules needed to properly style the below-the-fold content can be loaded only when the user scrolls down. 


Avoiding background-image property 

Ideally, a website would have a responsive background that a browser can load the appropriately sized image for different devices' screen widths or resolution. However, the background-image property in CSS lets you use only one image regardless of the screen size or resolution. This significantly impacts performance, especially when the end user is viewing the site on a low-end device or slow network.

Also, if you use background-image for your website's hero image, say, your browser won't download it until it has parsed the CSS — which means your hero image will not be prioritized and it will take longer to load. Apart from impacting the performance, the background-image property also has a negative effect on SEO, because Google does not crawl or index these. Furthermore, screen readers skip background-image entirely, which affects accessibility. 

Unless you're using a purely decorative background with no meaningful content, there's no good reason to use background-image. And even then, it's a good idea to use image-set in combination with background-image to counter the performance issues. Image-set lets the browser choose the most appropriate CSS image from a set of options.

The best solution to this is to either use the img property in HTML — especially for above-the-fold images — so that the browser can display it faster. As I explained in our blog post on optimizing images, the img property helps you properly optimize images, display differently sized responsive images based on screen sizes and resolutions, lets you use next generation formats like WebP, and more.


Optimizing fonts

Web fonts might look simple enough, but the browser takes a few seconds to process them, which might make your website slow. If a web font takes longer to load, the browser might delay text rendering. This has a direct impact on the First Contentful Paint (FCP) or the Largest Contentful Paint (LCP). Other than this negative effect on performance, if a font and its fallback font take up different spaces on the page, it could lead to layout shifts.

To increase performance, it's important to optimize fonts and use them carefully in CSS. The most direct solution for font optimization issues is to ensure that fonts are loaded as early as possible. Font files downloaded from third-party sites require separate connection startups, meaning you need to make sure your page's fonts are being requested in time for render. 

You could also inline font declarations and other critical styling in the main document instead of in an external stylesheet. 

Another thing to consider when optimizing fonts is how they're rendered. The font-display property lets you create a contingency plan for when a font has not loaded and informs the browser how to proceed with text rendering. Out of the five possible values for font-display, swap, fallback, and optional perform the best (in under 100 milliseconds). Depending on whether you prioritize performance or text rendering, you can select optional or swap respectively.

Using fewer web fonts — or fonts that do not need to be requested in the first place — like system fonts and variable fonts can also help boost performance. 


Automated solutions for CSS optimization

As always, the best way to optimize CSS is to write great code. If only that were always possible! Thankfully, there are several solutions that could automatically solve this problem for you.

Here are a few tools that optimize CSS, in ascending order of impact on performance.


Styled-components and Emotion

Styled-components was created with the goal of enhancing CSS for styling React component systems. It lets you write actual CSS in your JavaScript, which helps developers with easier deletion and maintenance of CSS and simplified dynamic styling, among other benefits. However, when used incorrectly, this might lead to more JavaScript, which also impacts site performance. 

Similar to styled-components, Emotion is a library designed for writing CSS with JavaScript. It  can be used for React or in a framework-agnostic approach. If used poorly, this could also lead to more JavaScript, which would also need to be optimized.


CSS Modules

CSS Modules are CSS files which are code split and locally scoped. Part of the compilation process, CSS modules let you import your .css file into a JavaScript Object. By making local scope the default, CSS Modules let you automatically avoid global scope when you write CSS. This makes it easier to maintain, modify, or remove CSS without breaking other things on your website.


Linaria

Linaria lets you write CSS, with the familiar CSS syntax, in JavaScript, but during build, the CSS is extracted to CSS files with zero runtime. It lets you use JavaScript for logic and makes a CSS preprocessor optional. This eliminates the added JavaScript issue and helps you create fast-loading pages.


Builder.io

Builder automatically generates all content with fully optimized CSS. Builder aggressively splits code, ensuring that, when loading a page or component, only the absolute needed CSS is included. Builder also serves minified, gzipped, and deduped CSS. The platform has no notion of CSS declaration order dictating style precedence, which means you can more effectively combine styles. All content is pre-rendered to optimized HTML, and all blocking scripts or styles removed. This way, Builder delivers content as very lightweight HTML. Any additional CSS for interactive elements are lazily loaded and hydrated after initial load.


Conclusion

Optimizing CSS might not be the most intuitive solution to vastly improving website performance, but just like unoptimized images and JavaScript, unoptimized CSS can block rendering and interactivity and harm user experience. Developers must pay particular attention to CSS file sizes using methods such as removing unused CSS and minifying their CSS files, prioritize critical CSS and lazy load non-render-critical elements only when needed, and optimize fonts and images carefully. These can all be performed automatically as well, saving time and effort, using a variety of solutions. To find out how you can best improve your website's performance and what solutions might help, try plugging your site into our free Performance Insights tool.


Share

Twitter
LinkedIn
Facebook
Hand written text that says "A drag and drop headless CMS?"

Introducing Visual Copilot:

A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot
Newsletter

Like our content?

Join Our Newsletter

Continue Reading
Web Development8 MIN
Server-only Code in Next.js App Router
WRITTEN BYVishwas Gopinath
April 3, 2024
Web Development8 MIN
Material UI: Convert Figma Designs to React Components
WRITTEN BYVishwas Gopinath
March 27, 2024
Web Development6 MIN
Qwik’s Next Leap - Moving Forward Together
WRITTEN BYThe Qwik Team
March 26, 2024