Understanding CSS Stats: How to Make the Most of the Numbers

In case you didn’t notice, the CSS analysis site cssstats.com received an overhaul recently. It’s a beautifully designed tool that gives you a lot of objective insight into your code, but how can you make the best use of CSS statistics? What should you shoot for? What do they mean, and how can you use them day-to-day?

Today, we’re going to talk about CSS best practices, specificity and maintainability, plus you’ll learn how to properly interpret and make better use of CSS statistics. Let’s dive in!

Quick Start Guide to CSS Stats

Head on over to cssstats.com, enter either the url of your website, its stylesheet, or paste the raw CSS directly into the textarea at the bottom and hit Go.

Once parsed, you’ll be given a ton of statistics about the CSS; from the number of rules used, their average size, breakdowns of each type of declaration, font and background colors, font families and sizes, and specificity graphs.

That’s what CSS Stats gives you, now let’s look at what we can do with all the data.

Focus on Maintainability

As front-end developers, we are constantly concerned about performance and user experience. We are also responsible for building software, but the word “software” is foreign to many front-end developers who come from a design background. It’s often easy to ignore best practices when we’re coding our CSS.

However, the truth is that front-end development, just like any other software development, requires focusing on best practices. The rules for best practices are abundantly discussed on the web, but for the sake of this article, we are going to hone in on what is arguably the most important practice as it relates to CSS: maintainability.

The maintainability of CSS centers on many different facets.

How easily can you design a particular module?

How easily can you design a modified version of that module?

Can a new developer comprehensively understand the systems your CSS employs?

Is your CSS predictable, consistent, and organized?

Are you relying on a preprocessor (or another tool) to make development and segmentation more flexible?

Do you repeat yourself often?

Are you using previously established naming and style conventions?

We won’t be diving into each of these items individually, but when we talk about maintainability, each of these considerations affect the overall maintainability of your codebase.

So, what do these stats tell you about maintainability?

The honest answer? Nothing, necessarily. You don’t learn anything about maintainability by simply looking at CSS statistics. You must also understand the context of that particular CSS, as well as the context of active development.

The first way to analyze your CSS stats is to look for signs of CSS bloat.

Bloat

By bloat we mean unused, redundant, or otherwise unnecessary CSS.

What scale of site is loading the CSS?

Let’s take, for example, a one-page application that has five different content modules. What kinds of CSS statistics would you expect a single page to have? A typical single-page application might have a fraction of the number of CSS rules and maybe half the number of color declarations as a large news publishing site or multi-faceted SAAS application.

If you are seeing an enormous number of selectors (for example, if your simple single-page site includes as much CSS as a web framework like Bootstrap, which clocks in at just under 2400 selectors), it’s likely that you’ve gone wrong somewhere. If you are loading in 30 font sizes and your design calls for 10, it’s likely that you have unused, bloated styles, or possibly inconsistent styles.

A possible exception to this rule, as it relates to maintainability, is if you are actually using Bootstrap or another popular, well documented framework; because the documentation on those projects is relatively deep and the usage has saturated the web, front end developers don’t necessarily maintain Bootstrap, as long as the primary source retains Bootstrap’s core implementations. However, if you are including the Bootstrap framework simply for the grid or a few UI elements, you should instead build a customized version that doesn’t include the extra CSS that you never plan to use.

What types of pages does the site load?

It’s possible that your application does something that necessitates a large number of selectors, colors, or font sizes. For example, if you are running an online store that uses product colors, it’s possible that a large number of colors could show up in your CSS and be a completely legitimate case. Another example is if you are running a site that allows users to select from a list of font sizes and fonts for content they create. In these examples, it makes sense to see large numbers in those particular categories.

Medium.com uses a font-size of 301px somewhere..

However, if you are creating something like, for instance, a blog with a limited color scheme, your CSS Stats should reflect that color selection and font declaration count.

Redundancy Between Rules

Do you define the same font size twenty times across your CSS? Very often this can be avoided, and is usually a result of a lack of planning. If you determine your font sizes before writing any other CSS, you will more easily be able to apply those sizes across the rest of the system.

The same is true for any repeated style; if you find yourself writing the same thing multiple times, perhaps that set of styles deserves its own presentational or semantic class or other modular definition?

Don’t go overboard here; redefining a few font sizes or background colors isn’t a big deal. However, redefining a number of styles multiple times on very similar modules may mean that you should be extending a base class. For example, if you have a button class:

Of course, there are many problems with this. First, it violates the DRY (don’t repeat yourself) principle. But why does that matter? Maintainability. Let’s say, for instance, that the design changes and calls for a smaller font on buttons. You then have to go into the .btnand the .btn-blue class to change the font size. Even more complication occurs when you need variants of the blue and regular gray buttons, like a blue-outline version. All of your changes to any one button have to be made to many buttons.

This is incredibly inefficient. Instead, you should be taking advantage of the fact that classes are modular, and allow you to define button styles that extend your base .btn class.

Aha! And now we have a much more maintainable solution, which also removes a significant number of lines of CSS and follows the DRY principle.

Specificity

Specificity is one of the harder-to-understand dark corners of CSS that often trips up even the most experienced developers. On CSS Stats, you can see a specificity chart that shows how specific the selectors are in your CSS, as well as where those selectors show up.

CSS specificity from the BBC’s website

This graph shows the specificity of selectors as they’re encountered in the CSS from bbc.co.uk. Imagine the left of the graph is the top of the stylesheet, then it moves along the x axis as it reads down the stylesheet. The more specific the rule, the higher the dark blue line on the y axis.

Specificity rules of thumb

We’ll provide three general “rules of thumb” to start out with, and then explain the rules.

Go from less specific to more specific

Shoot for lowest possible average specificity

Reduce the peaks in your chart

We’ll talk about each of these more in depth, but first let’s talk a little bit about how specificity works.

CSS selectors are assigned a specificity score to inform the browser rendering engine which rules apply to what elements. The reason this is needed is also the reason CSS is so powerful: styles can be inherited and cascaded in CSS. This means that you can apply more than one set of styles to any given element. The rendering engine must consolidate all of these rules and present something, but what happens when two different values are set for the same style declaration? For example:

a {
color: #fff;
}
a.button {
color: #000;
}

When the CSS engine encounters an <a> tag with a class of button, it must determine if the color attribute should be #fff, #000, or the browser default. CSS specificity is the ruleset the browser uses to make this determination.

Points

So, how does specificity work? Use this scoring system as a guide, taken directly from CSS Tricks:

Element selectors and pseudo-elements receive 1 point.

Class selectors and psuedo-classes receive 1,0 points.

ID selectors receive 1,0,0 points.

Inline styles receive 1,0,0,0 points.

!important trumps them all

* selectors get a specificity score of all 0s.

Note that in this scoring system, when something goes over 10, it doesn’t go into the next column, so for instance if you had a selector that was 11 elements long, it wouldn’t spill over to be a specificity of 0,0,1,1. It would instead be 0,0,0,11.

<a href="/" style="background-color: red;">
<!--
In this instance, the background-color
rule will have its own specificity
-->

a {
background-color: blue !important;
}
/*
In the previous example, we used inline
styles to set the background color to red.
However, if we applied this style with the
!important qualifier, it would override
the inline style.
*/

Okay - now that we have a basic primer out of the way for CSS specificity, how should that influence our code? Let’s go back to our three rules of thumb for CSS specificity.

#1 Go from less specific to more specific

This rule essentially states that general selectors should be at the beginning of your CSS, and more specific selectors should come later in your CSS. The reasons for this rule are many.

First, placing general rules at the beginning of your application usually sets the stage in your code for basic modules to be created. In conjunction with #2, having the least specific styles at the beginning ensures that you are writing with the least specificity possible first. Later, as your code evolves, adding more specific styles may become necessary to override or extend previous styles.

Styles on Apple’s website are heavily specific early on in the stylesheetThe Pure CSS framework’s specificity generally increases toward the end of the stylesheet

This leads to our second point: what happens when the CSS rendering engine encounters two selectors that have the same score? It still has to choose, so it will opt for the latter of the two rules. By erring to least specific at the beginning of your file, you are ensuring that your specificity overrides are more specific as you go later into the file. This means that a single class later in the file should be considered able to override single classes earlier in the file.

This practice will ensure that later development on the same project can quickly understand the cascading system.

#2 Shoot for lowest possible average specificity

If you’ve been a front-end developer for long, you’ve probably experienced the “CSS specificity war”. You write a selector and a few rules, then refresh the browser only to find the changes haven’t been applied. You know from past projects or from conversations about specificity that it’s because your selector isn’t specific enough, so instead of trying to trace back the problem to the selector that’s too specific, you decide to make the new one more specific. You add an ID or two, and if that doesn’t do the trick, you just throw !important at it. And, voila - your styles show up.

This approach works, technically speaking; but unfortunately, any time you want to extend that style, you have to continue to grow the complexity, and before you know it your selectors are extremely specific, and you’re having to repeat code rather than simply reuse classes. On top of that, it’s nearly impossible to determine exactly what level of specificity any new styles should have without adding more and more IDs and !important declarations.

Keeping your selectors less specific is a much saner, more maintainable way to handle your CSS.

A few pro tips:

By default, favor classes over IDs. This practice solves most specificity problems in one step.

Don’t nest your selectors further than three or four levels deep, and be certain that you need to nest. Nesting should only occur when extending a previously defined classes, and shouldn’t be used solely for code organization. Nesting can be used to future-proof your class definitions, but reusable classes should be used wherever possible.

#3 Reduce the peaks in your chart

This rule is primarily in place to avoid strangely placed rules. For example, if you are defining some classes for text presentation, and suddenly have a rule that nests six classes and an ID, that particular rule should be placed contextually with more specific selectors it is related to.

Conclusion

CSS Statistics can provide you with insight into the way your CSS is written, but this is only useful if you have an idea of what those stats should look like before trying to analyze them. This means having a deep contextual understanding of the way your CSS is written and why. If your CSS is maintainable and appropriate for the site it is used on, the statistics of that CSS aren’t reason enough to refactor your code.

Instead of following number rules blindly, as a responsible front-end developer, you should focus on making your code maintainable and reducing bloat. Statistics about your code may help you find problem areas, but they can only go so far.