Improving CSS performance and file size - an in-depth guide
Tags: css, webdev, productivity
Published: 2019-10-16 05:35:02

---
title: Improving CSS performance and file size - an in-depth guide
published: true
description: Improving CSS file size and performance results in faster loading and parsing times, and hardware accelerated animations. This article covers the methods of CSS file size and performance optimization.
tags: css, webdev, productivity 
canonical_url: https://blog.prototyp.digital/improving-css-performance-and-file-size-an-in-depth-guide/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/elytski1o23ybosxmors.jpg
---

## Table Of Contents
* [What makes CSS slow](#what-makes-css-slow)
  * [File size](#file-size)
  * [CSS rendering](#css-rendering)
* [Reducing CSS file size](#reducing-css-file-size)
  * [Minification](#minification)
  * [Optimization](#optimization)
  * [Compression](#compression)
  * [CSS structure](#css-structure)
* [Improving CSS animation performance](#improving-css-animation-performance)
  * [Transitions and animations](#transitions-and-animations)
  * [Promoting element into a composite layer](#promoting-element-into-a-composite-layer)
  * [will-change property](#willchange-property)
  * [contain property](#contain-property)
* [Bonus: CSS Performance tips](#bonus-css-performance-tips)

## What makes CSS slow?

### File size

Large file size results in larger download times and parsing times. It's simple as that.

### CSS Rendering

In order to understand where CSS rendering bottlenecks may come up, we need to look at the render pipeline steps:

**1. Style** - Determines which CSS rules apply to which elements in an HTML document.

**2. Layout** - Determines where the element is positioned on the screen and how much space does it take. CSS properties: `position`, `top`, `left`, `right`, `bottom`, etc.

**3. Paint** - Determines visual elements. CSS properties: `color`, `border`, `background-color`, etc.

**4. Composite** - Draws layers onto the screen. CSS properties: `opacity` and `transform`.

![The full pixel pipeline](https://thepracticaldev.s3.amazonaws.com/i/isrw4tppnca6qdol6k5y.jpg)
<figcaption>The full pixel pipeline (from Google Developers site)</figcaption>

CSS offers a lot of options in terms of animation and transitions. We can create a transition on a lot of CSS properties. There are transitions and animations which can use GPU and perform really well, resulting in smooth 60 FPS (Frames per second) experience with fluid and smooth animations. On the flipš side, there are CSS properties that, when animated, can result in low FPS and choppy animations.

Any changes or updates happening on one of the steps cause updates on the following steps. We can see that the **Layout step is the most expensive** to animate and **Composite step is the least expensive** to animate.

## Reducing CSS file size

By decreasing the file size of the CSS file, we can decrease the download time and loading time. Some improvements related to file size can be done even when we are finished working with CSS making it a very effective optimization. For maximum efficiency, it's best to keep in mind and apply these improvements from the start.

### Minification

CSS file minification is an easy win and should be the first step for achieving better CSS performance. Minification removes formatting characters inside the CSS file (whitespaces, line breaks, etc.) which are only useful to us (makes the code readable).

```css
/* Non-minified code */

.card {
  padding: 1rem;
  background-color: #aaa;
}

/* Minified code */

.card{padding:1rem;background-color:#aaa}
```

There are numerous online, automated and CDN **"uglifying"** tools that will help you with minification. Tools for CSS minification:
* [CSS Compressor](https://csscompressor.com/) - simple online minification
* [CSSNano](https://github.com/cssnano/cssnano) - Automated CSS optimizer + minifier
* [Clean CSS](https://github.com/jakubpawlowicz/clean-css) - Automated CSS optimizer + minifier


### Optimization

Wait... We've already minified our CSS file. Isn't it already optimized?

Well, technically it is. When talking about CSS optimization, we are looking at removing unnecessary CSS or reformatting CSS properties that reduce the number of characters. Unlike minification, this improvement cannot be done on CDN and it must be done when code is being compiled (by a tool like Webpack or Gulp).

Let's take a look at the following example.

```css
/* Unoptimized CSS */

.card {
  background-color: #aaaaaa;
  padding: 0.5rem 1rem 0.5rem 1rem;
}

.card__content {
    padding: 0.5rem 1rem 0.5rem 1rem;
}
```

At first look, this looks like any regular CSS that anyone would write and not think twice about it. But there are some optimizations that could be done to reduce the number of characters.

```css
/* Optimized CSS */

.card {
  background-color:#aaa;
}

.card,
.card__content {
  padding:.5rem 1rem;
}
```

We have reduced the number of characters from 132 to 85 (a 35% reduction). Let's apply minification and see the final result.

```css
/* Optimized CSS with minification */

.card{background-color:#aaa}.card,.card__content{padding:.5rem 1rem}
```

We have reduced the number of characters from 132 to 68 (48% reduction in total).

You can see how much CSS impact the optimization has. The reduction is a result of removing the DRY code which can be avoided in this simple example. Looking at the CSS file with thousand of lines of code which is being changed on a regular basis (especially if split into several files), we can easily make our code less DRY. Luckily, there are tools that help us optimize our code and keep it DRY.

In the previous section, we have mentioned two of the numerous tools for optimizing CSS with minification included:
* [CSSNano](https://github.com/cssnano/cssnano) - Automated CSS optimizer + minifier
* [Clean CSS](https://github.com/jakubpawlowicz/clean-css) - Automated CSS optimizer + minifier

### Compression

Compression is done server-side. It uses gzip or Brotli to compress and further reduce the file size in order to reduce the file download time.

This topic is very extensive and covers more file types than just CSS. CSS tricks wrote a [great article on this topic](https://css-tricks.com/brotli-static-compression/) if you are interested in implementing server-side compression.

It's also important to note that most CDN services offer the compression option out of the box.

### CSS structure

Having a good CSS structure and using various CSS best practices and also result in a lower-sized CSS file when minified. For example, using BEM and only class selectors with low specificity will result in fewer characters in the file and the lower file size.

I've covered CSS structure improvements in one of my previous posts. By following these CSS principles, you will have a CSS file with great structure, DRY code and a great foundation for optimization and minification.

{% link https://dev.to/adrianbdesigns/improve-your-css-with-these-5-principles-35jd %}

## Improving CSS animation performance

### Transitions and animations

We've covered the CSS rendering pipeline and what makes animation slow. So basically, **Layout step is the most expensive** to animate and **Composite step is the least expensive** to animate.

If we look at the CSS properties that cause the Composite layer to update, they are `transform` and `opacity`. These two properties use hardware (GPU) acceleration, resulting in very performant updates.

If you apply a transition to position attributes like `top` or `left`, animation performance will be poor because we are updating the **Layout** step which forces both **Paint** and **Composite** to update. Replacing the position CSS properties with `transform` and using transition on it, we are updating **Composite** step only, resulting in smooth animation.

### Promoting element into a composite layer

We aren't really restricted to using only `transform` and `opacity` for smooth animations. CSS offers quite a few ways of "promoting" an element into a composite layer to tell the browser that this element will have its Paint CSS properties updated often.

The hacky and "old way" of doing this is by either adding `backface-visibility: hidden;` or `transform: translate3d(0,0,0);`. In most cases, these properties won't affect your element in any way (if they don't override anything), but they will make the browser move the element into Composite layer, significantly improving animation performance.

```css
.example {
  width: 20rem;
  height: 20rem;
  background-color: #aaa;

  border-radius: 0;
  backface-visibility: hidden;
  transition: border-radius 0.3s ease-in-out;
}

.example:hover {
  border-radius: 50%;
}

```

### will-change property

A modern way of telling browsers which element is expected to be updated (in terms of CSS rendering) is setting the `will-change` property.

```css
.card {
  background-color: #aaa;
  transition: background-color 0.3s ease-in-out;
  will-change: background-color;
}

.card:hover {
  will-change: background-color;
}

.card:active {
  background-color: #bbb;
}
```

There are several things to keep in mind when using `will-change`:
* Don't apply will-change to too many elements.
* Use sparingly
* Don't apply will-change to elements to perform premature optimization.
* Give it sufficient time to work.

### contain property

The `contain` CSS property represents the future of CSS render pipeline optimization. Currently, it sits at limited browser support. It allows us to indicate that an element’s subtree is independent of the rest of the page. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page.

```css
contain: none; /* No optimization */
contain: strict; /* Equivalent to contain: layout paint size style */
contain: content; /* Equivalent to contain: layout paint style */
contain: size; /* component size is set and no descendant will modify its size.  */
contain: layout; /*  changes to any descendant of this element will not affect the layout of any outside element and vice versa.  */
contain: style; /* descendant’s styles will not affect outside elements.  */
contain: paint; /* you specify that no descendant will display outside the elements bounds. Similar to overflow: hidden; */
```

Example of using `contain` CSS property:

```css
.box {
  contain: layout size; /* Won't change size and won't affect layout */
}
```

```html

<div class="box">
  <div class="box__content">...</div>
</div>

```

## Bonus: CSS Performance tips

### Avoid using @import

`@import` CSS property is used to include a CSS file within another CSS file. The issue is that these files are then loaded one after another instead of parallel when using the recommended HTML way of including stylesheets.

### Use HTTP/2 if you have multiple stylesheets

HTTP/2 brings noticeable performance improvements when loading a lot of smaller files. This is an ideal solution if you are using CSS structure that results in multiple CSS stylesheets (individual screens, modules, components, etc.).

If you are not using HTTP/2, it's recommended to merge all your CSS files into a single CSS file.

### Be aware of "expensive" properties

Some properties are more resource-heavy and increase render time. If you are intending to support devices with lower processing power, being aware of these properties would be beneficial:

```
border-radius
box-shadow
filter
position: fixed

*
:nth-child
```

### Serve CSS file(s) over the CDN

Serving static files like images, CSS, JS, etc. from CDN improves download times. Additionally, some CDN services offer basic minification and optimization options, so you can easily get a performance boost if your code is not minified already.

### Keep your selectors simple

Having simple class selectors (consider using BEM and OOCSS or other flavors and combinations) can benefit performance when rendering your site, especially on devices with lower processing power. I've covered this topic more in-depth in one of my previous articles:

{% link https://dev.to/adrianbdesigns/improve-your-css-with-these-5-principles-35jd %}

<hr />

These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.

<a href="https://www.buymeacoffee.com/ubnZ8GgDJ" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-red.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>

Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.