8 CSS selectors DO’s and DON’Ts

Don’t describe style in selector names

Don’t

.blue-text { … }

Do

.highlighted-text { … }

There are two reasons for that:

  1. Your website colors can easily change. Maybe not from a complete blue theme to a red theme, but it may move a little bit in the hue wheel so that blue could become purple or grey. Make sure you don’t have to search and replace all selectors when you want to change a color. Or, even worst, make sure you don’t end up with something like this:
    .blue-text { color: red; }
  2. Describing the style in the selector makes very specific selectors. What if you want another tone of blue for another line? You could use .dark-blue-text. And then another, .light-blue-text. And another one, .light-blue-text-but-not-that-light… You see? That gets messy soon.

Selectors should describe purpose, not style.

Keep specificity as low as possible without using tag selectors

Don’t

.content #intro .icon { … }

Do

.intro-icon { … }

Seriously, specificity can be your worst nightmare when it starts skyrocketing. Try to keep it as low as possible.

Oh, by the way, NEVER use id selectors. Neither use !important. Never, ever.

Use one-class selectors when possible

Don’t

.button.active { … }

Do

.button-active { … }

This will keep specificity low and will avoid using too generic classes. What if another developer added .active { font-weight: bold; } somewhere else in the project?

Decouple selectors from HTML structure

Don’t

.header nav li button { … }

Do

.header-button { … }

It feels so good when you can change HTML structure and CSS keeps working…

Order selectors by HTML occurrence

Don’t

.footer { … }
.header { … }

Do

.header { … }
.footer { … }

There might be some elements with different order in the HTML code/DOM tree and the screen when they are rendered (absolute positioned elements, flexbox and grid children…). Order them with the same order they have in the HTML, not the way they are displayed.

Order selectors by specificity

The previous rule has an exception: when you’re ordering selectors applied to the same element.

Don’t

.list-item:first-child { … }
.list-item { … }
.list-item:last-child { … }

Do

.list-item { … }
.list-item:first-child { … }
.list-item:last-child { … }

A CSS rule should NEVER be overwritten by another rule appearing before. Remember, specificity can be your worst nightmare, ordering selectors by specificity makes it easier to understand the code.

Make all selectors referring to a page/component start with the same word…

I was using this rule before learning about BEM and I think it works very good in small to medium projects without having to carry with all the hard rules of BEM.

Don’t

.front-page-title { … }
.intro-home { … }
.home-text { … }

Do

.home-title { … }
.home-intro { … }
.home-text { … }

… and use that word as the file name

If you’re using a CSS preprocessor, a webpack loader or something similar you probably have your CSS divided in several files. Make sure all .home-xyz { … } selectors are in home.css (or _home.scss or whatever).

This way, given a class name, you will automatically know which file to look for.