How big should your CSS stylesheet be?

One acceptable answer would be ‘as big as it needs to be, but as small as you can make it’. But I expect you’d come here looking for a number, so here you go…

10 to 25 kilobytes (minified + compressed)

Happy? Probably not. It’s a fact that the number of bytes required to download a website is continually increasing, and so the likelihood is that your website falls outside of this range.

Why this number?

There’s no evidence-based reason behind the figures I’ve chosen. I’ve just built a lot of small to medium sized websites and this is the range these websites tend to fall within. Sure, if I was building a huge website the size probably will creep up, but then I’d consider if splitting the CSS into multiple files would have any benefit.

With less stuff to style across fewer pages the file size of my stylesheets might be smaller than yours, but are you sure your CSS files are as optimised as they can be? I’m not sure mine are.

Why do we want a small stylesheet?

Hopefully this one is more obvious. When we start building a website we might start with a single blank file. Every bit of content, images, styling or piece of functionality results in one of three things…

  1. More bytes for the user to download
  2. More complex websites for a browser to render
  3. More complex actions for the server to perform

When it comes to the file size of our stylesheets, we’re pretty much focused on point 1. A website can only load as fast as a user’s Internet connection allows the data to be transferred. The more data we send (which may also cost users), the slower it renders and having a slow website then leads to other problems.

But the Internet is faster now, why should we care?

Sure, the Internet is getting faster… for some people. But have you ever been in the car on a spotty mobile connection unable to find the answer to a random discussion like how many episodes of Friends were made? 236 by the way.

While these connections can be so bad that you’ll never find the answer, a user is certainly going to be staring at a blank screen far longer if the overall page weight of the website is larger than it needs to be.

We can’t always expect every user to be on a superfast connection, and so we have to consider site speed in every decision we make.

So how do you achieve such a small file size?

As I mentioned, the sites I build for Bronco aren’t comparable to huge behemoths like Amazon or Facebook. Therefore, it’s difficult to know if my CSS files are as optimised as they could be, maybe the reason I can achieve such small file sizes is that the websites we build are just not as complex.

But, with that in mind, here are some of the features of the stylesheets I produce…

Minify & Compress

Every stylesheet I create is minified and compressed. For minification I utilise the Gulp task runner, taking the headache out of having to do this manually.

For compression we have either Gzip or Brotli installed on our servers and it’s the single biggest thing you can do to reduce your CSS file. On this website we use Brotli and it converts a 91kb file on the server in 15kb of data transferred to the user. That’s an 83% reduction in file size.

How much the file can be compressed will depend on how you write your CSS, but that’s a far more complex subject than we can cover here.

Sass/SCSS

For some years I’ve used the Sass pre-processor to make authoring and maintaining my CSS easier and quicker. Features such as nesting, variables and partials all help in reducing the time it takes to author my CSS and with Gulp the SCSS is processed in the background after each change is saved.

One downside to using Sass is that you can become separated from the resulting CSS file that users will download. It’s likely you’ll rarely open that file and understand how your SCSS is being converted and so can begin picking up poor habits, especially concerning nesting.

Nesting is a great feature that can improve readability of your editable SCSS files. However authoring Sass like the following example leads to overly specific CSS selectors that are unnecessary and lead to a bigger file size.

.card {background:#FFF;
	.card__title {color:#000;}
}

Becomes…

.card {background:#FFF;}
.card .card__title {color:#000;}

BEM Methodology

To help avoid the trap of overly specific selectors due to nesting I also utilise the BEM methodology. I find the two work really well together. The above example then becomes…

.card {background:#FFF;
	&__title {color:#000;}
}

and the css output is…

.card {background:#FFF;}
.card__title {color:#000;}

Whether I use BEM exactly as it’s meant to be used throughout the website I’m building is another matter. I find myself questioning if I everything I need to style should have a class or if it’s still appropriate to do the following…

.block {
	&__element {
		&--modifier {
			span {background:#000;}
		}
	}
}

The resulting CSS is…

.block__element--modifier span
/* when it could be */
.block__element--modifier__tag

There’s no difference in the number of bytes the two add to the file. Instead the differences are likely to be more noticeable in how quickly the browser renders these elements, but that’s a whole other deep dive into the efficiency of different CSS selectors.

Utility Classes

For a long time I resisted the use of utility classes as they’re pretty much the exact opposite to what the BEM methodology aims to do in ensuring that classes are semantically descriptive and that classes aren’t so generic like this example…

<div class="green-text grey-background text-size-xl"></div>

I’ve always opposed using classes in this way, but sometimes you just want a class to do something without having to create new class names or new files to only add a margin to an element.

When beginning to work with the WordPress Gutenberg Block editor it was necessary to have classes such as .has-green-color or .has-grey-background-color. In building sites using these classes I became more relaxed about using utility classes for colour, spacing and a few other rarities.

I find that utility classes for margin and padding especially are a great help and allow me to tweak layouts more granularly based on surrounding elements rather than expecting that element to require the same spacing in all instances. That doesn’t mean I don’t declare margin and padding directly for many elements, it’s just the utility classes come in useful too.

The downside to utility classes is you’re likely to have CSS that is not only unused on certain pages, but unused throughout the whole website. This is one of the reasons I’ve never entertained using frameworks like Bootstrap, but with utility classes resulting in a low increase in additional bytes in the final CSS file I believe the benefits outweigh the cost.

Nested Media Queries

Another feature of my CSS files that has the potential to increase the overall size of my files is duplicated media queries through nesting in Sass.

Take the following example…

.foo {font-size:30px;
	@media screen and (max-width:680px){font-size:24px;}
}
.bar {font-size:20px;
	@media screen and (max-width:680px){font-size:14px;}
}

The resulting CSS becomes…

.foo {font-size:30px;}
@media screen and (max-width:680px){
	.foo {font-size:24px;}
}
.bar {font-size:20px;}
@media screen and (max-width:680px){
	.bar {font-size:14px;}
}

So, we’re getting repeated media queries that could be merged into one. In many instances I try to consider where I place my media queries that exist within a single partial file in order to reduce duplication, but don’t do this for an entire website due to the issues it creates in maintaining the website in the future.

At one time I would use a Gulp task to combine the media queries at the base of the file, however these tasks began failing or causing unexpected issues often relating to the order in which the media queries were combined.

If there’s evidence that this causes huge increases in the size of my CSS files I would look again at alternatives.

Further Reading : Critical Path, Preload & HTTP/2 Push

These aren’t directly related to the size of the CSS files but certainly areas you should investigate if you haven’t already.

Critical Path CSS concerned inlining the critical CSS for a page within the <head> and then delaying the loading of your entire CSS file. Often this can be a bit of maintainability nightmare, but its certainly something to consider and pre-processors can help.

Preload and HTTP/2 Push are easier to implement though aren’t supported by all browsers or enabled on all servers. In the case of preload you’re effectively telling the browser to request the CSS file at a point before it would usually do so, meaning the file is downloaded quicker and is less likely to be render blocking.

For HTTP/2 you’re sending a request to the server that the CSS file should be sent at the same time as the HTML page is sent to the browser, making sure an important file is there as soon as the browser needs it in order to render the website.

Need Help?

Still not sure what you can do, or how to do it. Maybe we can help? Get in Touch and we’ll let you know.


We'd love to hear from you!

If you think Bronco has the skills to take your business forward then what are you waiting for?

Get in Touch Today!

Discussion

Add a Comment