Meaningful selector specificity measure

See comments

I searched for an easy way to communicate the selectors weight. A way to measure that implicitly helps to follow CSS best practices. A simple solution that you can use today.

How it actually works

The specificity determines which CSS rule will be applied. The more a rule will be specific and the more it will have priority on the others.

For the browsers, the CSS selector specificity is evaluated with a group of 4 different counters. Each counter is infinitely greater than the next one:

  1. Inline style;
  2. IDs;
  3. Classes, pseudo-classes & attributes;
  4. Elements & pseudo-elements.

Some examples of selectors increasingly specific:

a { }                     /* 0,0,0,1 */
.button { }               /* 0,0,1,0 */
input[type="submit"] {}   /* 0,0,1,1 */
#header {}                /* 0,1,0,0 */
#header a {}              /* 0,1,0,1 */
#header a:hover {}        /* 0,1,1,1 */
#header a:hover::after {} /* 0,1,1,2 */

The problem with browser counters

The browser counters are actually the way to measure that is the most accurate. But it is not adapted to humans and it could be hard to communicate with this format:

  • We are not used to manage several counters for one measure;
  • This counters does not represent something concrete for us;
  • It is hard to communicate, both oral or written, it often results in bad approximations.

A meaningful unit

Here is some rules that you could follow when you share a selector specificity:

  • Inline styles has a value of infinity,
    means “we can not surpass it”;
  • Every ID has a value of 1000,
    means “it is something big”;
  • Every class has a value of 1,
    means “it is what you should use most of the time”;
  • Every element has a value of 0.1,
    means “it annoys everyone to count it”;

It's a good simplification for daily use, for yourself or to share a measure with another developer. When you have to write it, you could use the mw unit for “meaningful-weight”.

The previous example with this way to measure:

a { }                     /*    0.1 mw */
.button { }               /*      1 mw */
input[type="submit"] {}   /*    1.1 mw */
#header {}                /*   1000 mw */
#header a {}              /* 1000.1 mw */
#header a:hover {}        /* 1001.1 mw */
#header a:hover::after {} /* 1001.2 mw */

Note: This is still an approximation, so you still have to understand the browser counters.

tl;dr

A nice way to measure selector specificity: ID=1000, class=1, element=0.1

Happy coding, Thomas Zilliox.

comments powered by Disqus
That's my face!

About me

I am Thomas Zilliox, a freelance web developer. I help web teams to reduce CSS maintenance & evolution costs.