CSS with only class names

I wanted to make a note to myself and a reference for any co-working front-end colleagues about the good old problem of structuring your stylesheets.

These days we anyway got rid of id selectors and attribute selectors, so the only common selector that left is the tag selector.

First let me make some exceptions.

  1. If you use a front-end framework similar to React, Vue.js, etc. please use CSS Modules or whatever is the recommended way for styling with that framework.

  2. Although these days is controversial, I still use a css reset and on the contrary to the article, there should be mostly tag names selectors there.

  3. Styling markup which is not generated by you ( e.g. markdown parsed content or any plugin that adds HTML to your page ) should be an exception and should have a wrapper element around it .markdown h1, .markdown h2 { }.

Now back to the point.

What is "CSS with only class names" anyway?

Every element that needs to be styled, needs to have an associated class name, used as a selector in your CSS.

Structuring your CSS is a question as old as the job title "Front-end developer". These days most of the community came to the decision of using a methodology for styling ( e.g. BEM, OOCSS ), which is anyway built on top of styling with class names philosophy.

The problem that I want to address is that no matter what you style - A single landing page with 100 LOC HTML, a complex application, a WordPress template or just writing an example on Stack Overflow - you should use exclusively class names for styling.

Yep, this means that :

.footer { }
.text-input { }
.title { }
.some-list { }
.some-list--item { }
<footer class="footer"></footer>
<input class="text-input" type="text" />
<h1 class="title"></h1>
<ul class="some-list">
    <li class="some-list--item"></li>
</ul>

is better than :

footer { }
input[type='text'] { }
h1 { }
.some-list ul { }
.some-list ul li { }
<footer></footer>
<input type="text" />
<h1></h1>
<div class="some-list">
    <ul>
        <li></li>
    </ul>
</div>

So let's go with the reasons.

Maintainable stylesheets

So you have this shiny CSS + HTML combo delivered by someone and you want to add / remove a piece of it.

Styled tag names will lead to a descendant selector in most cases. Or even worse - an over-specified selector h1.title, which is not a good idea anyway. Adding or removing a set of elements will require you to make sure that descendants are styled as before ( not accidentally break something ) or that you don't accidentally remove a CSS rule that was used somewhere else.

With class names only, adding a new element is either reusing a class name(s) or simply writing a completely new one. Removing is just a search across the html and find the usage of the class that you want to remove.

Developer performance

Having tags and classes introduces a new layer of complexity which results in a time consuming choice of "Should I style the tag or use a class name?"

This can go even more complicated and one can think about "Should I use a footer input or .footer-input?". Having to think about the rule is something eliminated by using only class names.

Whenever you need to style a new element, which looks like no other, just invent a new class. Fast & simple. You don't have to think so much about the consequences anyway, since refactoring is now easier.

Refactoring CSS

Using a single grep "my-class-name" *.html" will give you all elements that are styled by your rule. On the other hand having the necessary nesting ( descendants ) of tag-styling will require an understanding of the whole tree before you can recognize if a rule is being used or not.

Removing dead CSS code is quite easy as well. You will be absolutely sure that the class is not being used if it does not exist in your codebase.

Renaming a conflicting rule ( see below ) is a global search-replace and nothing more.

Refactoring HTML

Having the same looking h1 tag on every page, sounds as a good idea, until you meet a SEO specialist.

Another good one is a-tag vs button-tag debate and how should they look. Almost always comes in handy to switch them without much effort.

Changing the tag name without changing the CSS is a huge benefit. It means that you have decoupled the presentation from your structure.

Portability

Not so long ago I had the task to replace gradually the design of a legacy CMS-based website. We started with a new header and footer. The new code, styled without tags and wrapped around a container was very easy to inject into the old legacy website. We did the job in no time, thanks to our unique, class name based CSS rules.

Using only class names usually leads to non-conflicting rules and makes possible adding a separate stylesheet file to another page without any side-effects.

Having even one global h1 { } will make your job much harder.

Browser performance

Although I think the performance benefit is not the major reason. I would like to note that too.

A nice explaination of what is a fast selector you can read in the awesome CSS Guidelines.

Summary

Use only class names as your CSS selectors, because :

  1. Your HTML / CSS is easier to maintain.
  2. Is faster to develop.
  3. Is faster to refactor.
  4. Is more portable.
  5. Is faster for the browser.

Special Thanks

Big thanks to Burak Barakaci, who helped me stop styling tag names 4 years ago!