CSS Good practices
In the past CSS had such limitations and was so badly understood by most developers that using frameworks or libraries was seen as the only way to get things working. Bootstrap was the king of CSS frameworks and with it came a ton of code that was most often not used at all. The only usable alternative was probably Foundation or SASS libraries like Susy.
Fortunately today we have a lot of choice! We still have Bootstrap, but also lighter alternatives like Bulma or totally different propositions like the utility first Tailwind. Also tools like Purge CSS can help reduce the size of CSS bundles by removing the unused parts of CSS frameworks.
In reaction to fully equipped frameworks we've also seen class-less CSS frameworks rising in popularity for a few years and they come with the promise of a small file size that correctly styles a website with only the HTML elements. That indeed sounds like a smart idea as it forces the developer to use semantic HTML.
But if you have to extend this kind of framework with your own design and don't want to use classes, you're going to create more troublesome code that you think.
Enters specificity
Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of different sorts of CSS selectors.
So what are the more specific and less specific things you can meet in CSS? Here's a list from more to less specific:
- IDs
- Classes, attributes and pseudo classes
- Elements and pseudo elements
Knowing this, some practices can create a lot more specificity than others. Among them, these are the worst:
- Using IDs as they are single use.
- Nesting selectors, for example
.navigation .navigation-list
doubles the specificity of the later and prevents it from working outside the former. - Qualifying selectors, the action of sticking a class to a specific HTML element like
ul.navigation
Specificity is why a lot of people hate CSS:
- It makes it hard to extend an existing code base if everything is super specific
- It can trigger repaints of existing elements, thus creating flashes when loading the website
- It makes the code super verbose and hard to maintain
- It creates code segments that can't be reused in another situation
So as you can see, it's not just a technical thing but a good practice methodology to take specificity seriously.
Chain elements or use a class?
To come back to our no-class CSS topic, we find ourselves in front of a dilemma.
Let's say you want to add red to your links located in a list in the navigation of your website, using only HTML elements and no classes. It would look like this:
nav ul li a {
color:red;
}
Since browsers read CSS from right to left, each time they meet a new element in this declaration, they have to re-compute the design. This is how the browser interprets this chain:
- I style links to red
- Wait it's only links in lists that need red
- Crap, it was only links in lists in the navigation that need red
Unless you have a terribly big CSS file that takes a lot of time to be parsed and triggers a lot of refresh, of course you will not see this happening. But this is still happening under the hood.
Now let's compare this to a simple utility class:
.redcolor {
color:red;
}
<a class="redcolor">
With this code, the browser only thinks if I see a redcolor class, I add red. And that's it, no repaint, no problem. But here's the thing: chaining HTML elements is calculated as less specific than using a class.
So who is right and who is wrong? The browser is right, but ultimately, the no-class CSS is worse:
- It's more verbose
- It's harder to extend the existing code and will get even more verbose when doing so
- It can't be reused in another context since it's tied to specific parents
So in the end, using class is a better idea. The no-class CSS methodology is good, but only works as a starter point for global elements.
Tips and tricks for your CSS
So in the end what should you do if you want to maintain small CSS file size and low specificity? Here are some rules that you can apply to almost every project:
- Style HTML elements for broader usage. The moment you start chaining them means you need a class
- Never nest or qualify classes and instead, use a simple yet effective naming methodology like BEM, Block Element Modifier
- Try to organize your CSS file with less specific elements at the top and ery specific elements at the bottom, which is often referred to the Inverted Triangle methodology
- Using a methodology like BEM might help you think about your CSS classes as objects than can be reused and extended, a good practice called Object Oriented CSS
You can check your specificity using this specificity calculator and check if your file has his specific code in order (from less to more) using this specificity graph generator.
By doing this your code will be lighter, easier to maintain, reusable and extendable like objects, and won't trigger repaints.