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
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.
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.
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.
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
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.
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
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.