CSS – Overqualified or more specific selectors?

How many times have you seen CSS like this?

img.alignleft {
  float: left;
  display: inline;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);

img.alignright {
  float: right;
  display: inline;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);

If you were to run this through CSSLint, one of the warnings it throws would be “Disallow overqualified elements”. To quote this CSSLint documentation for this warning:

Writing selectors such as li.active are unnecessary unless the element name causes the class to behave differently. In most cases, it’s safe to remove the element name from the selector, both reducing the size of the CSS as well as improving the selector performance (doesn’t have to match the element anymore).

Removing the element name also loosens the coupling between your CSS and your HTML, allowing you to change the element on which the class is used without also needing to update the CSS.

While the reasoning given is quite understandable and rather sound, when I started out in webdev this was not reasoning I learned anywhere. I learned that you never use the HTML element you want the class applied to (overqualify the selector). I am not sure how I came to believe this or even why, it could have been from CSSLint telling me not too, but it is what I thought and subsequently practiced.

As time passed and I gained more experience while I continued learning, I found this “truth” I had known to be a lie. It was OK but not necessary to have an overqualified selector. You see, normally when we use a class we want to apply that styling to multiple elements of possibly different types (<p> and <div>, for example). That is why we would leave off the HTML element in the selector: it “loosens the coupling between your CSS and your HTML”. It does not mean it must be left off no matter what. As the CSSLint documentation also explains, their overqualified selector warning will not fire “if two different elements are found with the same class name (i.e., li.active in one rule and p.active in another)”, as they show in the following example:

/* Two different elements in different rules with the same class */
li.active {
    color: red;

p.active {
    color: green;

Through my experience, though, I have often come across another case that CSSLint would declare as “overqualified” but is more-or-less a deliberate style choice, you might call it. CSSLint cannot understand the concept, thus it flagged the code. What is the concept? More specific selectors. The first example in this post is declared overqualified because we are restricting the .alignleft and .alignright classes to HTML <img> elements- but perhaps that is the point? There may not be other elements where we want the classes applied. Even if there were other page elements we wanted floated to the left or right, do we want them to receive the box-shadow intended only for images? Not really, no. In our case here, CSSLint does not understand our deliberate actions but, through “blind” static analysis, it “thinks” we are doing it wrong and flags us for it.

Obviously with some refactoring we could ake CSSLint happy, but that is not the point here. The point is to not always blindly follow what our linting tools tell us. Just like the old saying “Can the blind lead the blind? Will they not both fall into the ditch?”, blindly listening to the tool’s blind analysis will cause us to stumble. We should look up what the warning means, why it is being thrown, what can be done to satisfy the warning, and if we should ignore it altogether per style guidelines or deliberate choice, like with the deliberately more-specific (and not overqualified) selector example above.

Hopefully this small tutorial has been of help to you and maybe (who knows?) cleared up the same confusion on CSS classes and qualified selectors that I had. 🙂