Welcome to WebmasterWorld Guest from 54.146.230.149

Forum Moderators: not2easy

Message Too Old, No Replies

# CSS Specificity Calculation

## A Small Excerpt That Some May Find Useful

#### cmarshall

12:19 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

META Note: This is a small excerpt from a series that I'm writing up in a blog, so please understand that it will be incomplete. I just thought that it might be useful.
--
The "Scientific" Way to Calculate Specificity
In the last posting, I ended with a note that outlined the four ways to determine specificity:
1. Create a basic mathematical-style formula.
2. Succumb to The Dark Side, and develop Sith powers [stuffandnonsense.co.uk].
3. Burn incense, shake ju-ju sticks and hope the Gods are smiling.
4. Fly by the well-educated and experienced seat of your pants.

In this posting, I'll cover the first method.

Just a warning: If you are someone who has seen real math and algorithms in action, this may seem silly. If you are the "artsy" type, who likes to avoid things that smell like math, then you won't like this. However, this is an excellent technique for determining an exact level of specificity. It's not "junk science." It works.

I'd link to other sites, but, you know, it's rather silly. They all seem to want to squabble with each other. The only one that I like is Andy Clarke's site [stuffandnonsense.co.uk], and that's because he brings such a great attitude to it. His explanation is a wee bit light on details, but pretty useful, nonetheless. I think that most of you would prefer using his method over the one I'll outline on this page.

For the record, this is the official word on calculating specificity [w3.org]. It was written by the folks who wrote the standard. Think of it as "going back to the BT." It's muddy and obtuse, hard to read, but 100% accurate.

Here's my take on the matter:

First of all, I like to take into account inherited specificity (what I referred to as specificity level 1). This isn't usually accounted for in other people's calculations. It's very weak, and usually not an issue, but it does play a part, and I have been dinged by not taking it into account.

I also ignore inline styles. Besides not being the "proper" way to do it, they trump everything else. Declaring an inline style is the nuclear option.

As a general rule of thumb, I always use the lowest specificity possible in any given situation. This is critical if you are writing code that might be modified by others. The lower the specificity, the more easily it can be "stepped on" by subsequent styles.

Okay, I now assign an "exponent" to the specificity levels:

1. Inherited Specificity from an enclosing element is Just Plain 1 (Exponent 0)
2. Element Name Specificity is Exponent 1 (10, 20, 30, etc.)
3. Class Attribute Specificity is Exponent 2 (100, 200, 300, etc.)
4. ID Attribute Specificity is Exponent 3 (1000, 2000, 3000, etc.)

There will be two places that you need to calculate specificity:

1. In the element that will be affected.
2. In the rule selector.

The first is the specificity that must be exceeded in order for a property to become effective, and the second is the specificity applied to the rule's properties. Remember that specificity is actually something that is applied to CSS properties, not rules, and that every element has CSS properties applied to it.

This is a good time to throw another monkey wrench into the works. Certain elements have inherent (not inherited) properties. If you noticed, some of the text in example 48 was separated from the text above and below. This is because that text was in <p> elements, and paragraphs have inherent top and bottom margins to them. The specificity of these properties is also at the specificity exponent of 0. This was why I chose the <div> element as an exemplar of a block element. <p> elements are also block elements, but come with a bit of "baggage."

The specificity is fairly easy to calculate for rule selectors, not so simple for elements.

Let me take the opportunity to introduce you to an interesting online tool: a specificity calculator. Paste your code into the text box, and it will catalog the specificity of the elements of your code. To be honest, I'm not that enamored of it. I much prefer using my brain, eyeballs and Firebug. Firebug is just so goddamn kewl that I can't give it enough praise.

Into Action
Okay, time to get the show on the road. I've outlined the various levels of "exponents" we'll use to calculate the specificity of our rules (not elements). The way it works is we count the number of times various levels of specificity are represented in our rule selector, and multiply our exponent for that level by the number of occurrences. Here's an example:

Let's say that this is our rule (shudder):

`div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

Here is some markup for the above:

`<div class="enclosing">  <div class="some_class" id="a_div">  <p>  This is <span class="another_class"><em id="this_em">italicized</em></span> text.  </p>  </div> </div>`

Count all the general element names:

`div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

There are 4 of them. Multiply them by the "Element Name Specificity Exponent," which is 1 (or "10"), and you get:

40

Next, we count the class names:

`div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

There are 2 of these. Multiply them by the "Class Name Specificity Exponent," which is 2 (or "100"), and you get:

200

Finally, we'll go to the element IDs:

`div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

There is only 1 of these. We multiply this by the "Element ID Specificity Exponent," which is 3 (or "1000"), and we get:

1000

The "quick and dirty" way to get the specificity is to add them together:

1240

In order to overrule either of the properties in this rule, another rule needs to have a greater specificity, or have the exact same specificity and be declared after this rule.

We can say that the <em> element with an ID of "this_em" has two CSS properties applied to it:

font-weight:lighter, at specificity level 1240, and font-style:italic, at specificity level 1240.

Let's add another rule to the mix:

`div .some_class p span.another_class em#this_em { font-weight:bold } div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

We want to make the text bold, as well as italic. That means that we need to override the "font-weight:lighter" property of the element.

Again, we'll calculate the specificity for this:

Count all the general element names:

`div .some_class p span.another_class em#this_em { font-weight:bold }`

There are 4 of them. Multiply them by the "Element Name Specificity Exponent," which is 1 (or "10"), and you get:

40

Next, we count the class names:

`div .some_class p span.another_class em#this_em { font-weight:bold }`

There are 2 of these. Multiply them by the "Class Name Specificity Exponent," which is 2 (or "100"), and you get:

200

Finally, we'll go to the element IDs:

`div .some_class p span.another_class em#this_em { font-weight:bold }`

There is only 1 of these. We multiply this by the "Element ID Specificity Exponent," which is 3 (or "1000"), and we get:

1000

1240

Now, do we think that this will work? We have another rule with exactly the same specificity.

Nope. Can you see why?

The specificity values are exactly the same, but the new rule is declared before the old one. Let's change the order:

`div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic } div .some_class p span.another_class em#this_em { font-weight:bold }`

Now it works.

Here's another way to trump the font-weight:

`div.enclosing .some_class p span.another_class em#this_em { font-weight:bold } div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

This increased the specificity of the rule to 1340.

This also works:

`body div .some_class p span.another_class em#this_em { font-weight:bold } div .some_class p span.another_class em#this_em { font-weight:lighter;font-style:italic }`

This increases the specificity to 1250.

Again, this applies to the rule selector. There's no simple way to do this for an element. What you need to do is go over the rules carefully, and figure it out, or do what I do: inspect the element with Firebug, and see where the errant style properties are coming from, or see what level of specificity needs to be overcome to apply a new style.

The simple "add them together" method will work fine, until you have counts over 9 for any of the parts of the formula. In this case, you can express the specificity like this, instead:
10000,200,50,0
You can also remove the "exponents," as you don't need them anymore:
10,2,5,0
ANY number in a left-hand group beats ANY number to its right. For example:
1,2,5,9
The "1" beats everything else.

A "Gotcha"

In these examples, I made the <em> element's rule specify a property of "font-style:italic". In reality, this is unnecessary. Most browsers render <em> elements as italic anyway (this is an inline element with "baggage"). The following will work just as well:

`div .some_class p span.another_class em#this_em { font-weight:lighter }`

Note that I removed the "font-style:italic".

Remember that I like to take into account inherited and inherent properties. In the case of the <em> element, the font-style:italic property is inherent.

Inherent always beats inherited, but nothing else. It is the same specificity level of inherited, but acts as if it was declared afterwards, so it overrides the prior declaration. For example:

`div.enclosing { font-style:normal } div .some_class p span.another_class em#this_em { font-weight:lighter }`

Will not override the italic representation inherent in an <em> element.

See for yourself:

The reason for this is that the "font-style:italic" declared in the enclosing <div> is only at specificity level 1 when it gets to the <em> element. The element's inherent italic style overrides it.

We can fairly easily override the italic style like so:

`em { font-style:normal } div .some_class p span.another_class em#this_em { font-weight:lighter }`

This applies a specificity level of 10 to the element, which overrides its inherent specificity level 1 property.

The biggest place that this tends to affect people is in the styling of anchor elements (<a> elements). These have an inherent style that is usually "color:blue;text-decoration:underline". There are some other things, called "pseudo classes" that also affect many elements (especially anchor elements), but that is a topic for another posting.

The !Important Rule

The !Important rule is a way of coercing a CSS rule to trump even the highest level of specificity and inline styles.

Let's look at how this works. We'll start with an example in which the font-weight property of the <em> element is overloaded with very great specificity:

`<html>  <head>  <title>Example 57</title>  <style type="text/css">  em { font-weight: normal }  body#body_id div#enclosing_id div#some_id p#some_p_id span#span_id em#this_em { font-weight:bold }  </style>  </head>  <body id="body_id">  <div id="enclosing_id">  <div id="some_id">  <p id="some_p_id">   This is <span id="span_id"><em id="this_em">italicized</em></span> text.  </p>  </div>  </div>  </body> </html>`

Using our calculations, we see that the bold font-weight property value is applied with considerable vigor. It has a specificity value of 6060. The normal weight is applied at a value of only 10.

However, look what happens if we apply the !important rule to the normal weight:

`<html>  <head>  <title>Example 58</title>  <style type="text/css">  em { font-weight: normal !important }  body#body_id div#enclosing_id div#some_id p#some_p_id span#span_id em#this_em { font-weight:bold }  </style>  </head>  <body id="body_id">  <div id="enclosing_id">  <div id="some_id">  <p id="some_p_id">   This is <span id="span_id"><em id="this_em">italicized</em></span> text.  </p>  </div>  </div>  </body> </html>`

We see that this trumps even the very specific declaration. This will even override an inline style:

`<html>  <head>  <title>Example 59</title>  <style type="text/css">  em { font-weight: normal !important }  body#body_id div#enclosing_id div#some_id p#some_p_id span#span_id em#this_em { font-weight:bold }  </style>  </head>  <body id="body_id">  <div id="enclosing_id">  <div id="some_id">  <p id="some_p_id">   This is <span id="span_id"><em id="this_em" style="font-weight:bold">italicized</em></span> text.  </p>  </div>  </div>  </body> </html>`

This means that you need to be very careful when using the !important rule, as it makes the property value virtually impossible to override. The only thing that is more specific than !important is another !important, applied to a rule of the exact same (or higher) specificity of the original rule.

This example allows bold to override the !important rule, as the new rule is after the original, and is of the same specificity:

`<html>  <head>  <title>Example 60</title>  <style type="text/css">  em { font-weight: normal !important }  em { font-weight: bold !important }  body#body_id div#enclosing_id div#some_id p#some_p_id span#span_id em#this_em { font-weight:bold }  </style>  </head>  <body id="body_id">  <div id="enclosing_id">  <div id="some_id">  <p id="some_p_id">   This is <span id="span_id"><em id="this_em">italicized</em></span> text.  </p>  </div>  </div>  </body> </html>`

This one does as well, because the !important is applied to a rule with a higher specificity:

`<html>  <head>  <title>Example 61</title>  <style type="text/css">  em#this_em { font-weight: bold !important }  em { font-weight: normal !important }  body#body_id div#enclosing_id div#some_id p#some_p_id span#span_id em#this_em { font-weight:bold }  </style>  </head>  <body id="body_id">  <div id="enclosing_id">  <div id="some_id">  <p id="some_p_id">   This is <span id="span_id"><em id="this_em">italicized</em></span> text.  </p>  </div>  </div>  </body> </html>`

Is It Worth It?

How much time should we spend carefully calculating the specificity of each of our style rules? We can easily take this too far, and spend ages making sure that we know exactly how specific each rule is, but that can take a very long time, especially if you are modifying a CMS (like this site does). A CMS will usually have dozens of styles in its theme; sometimes, with rather careless specificity.

The time to be exact is if you are writing code that is meant to be overloaded by others. In this case, you want to use the lowest specificity possible. I try to be careful of this in all code I write, but it is quite possible to get too anal-retentive about this stuff. If you examine this site's CSS, you will see a number of !important rules. Sometimes, the fox just ain't worth the chase. Use your judgment.

Conclusion

This concludes (whew!) my lecture series on the three basic foundations of CSS-based design:

1. The concept of separation of presentation from structure
2. The two main CSS display modes: block and inline
3. The concept of CSS specificity

With these, we are well on our way.

This just scratches the surface of CSS-based design. I'll cover more as time allows, but this is a good start. I sincerely hope that this has helped to give an understanding of the important basics of using CSS properly.

#### sgietz

12:48 pm on Apr 21, 2008 (gmt 0)

#### Full Member

joined:Jan 17, 2007
posts:306

Yikes!

Dude, it's Monday morning. How could you do this to us?

:D

#### cmarshall

1:09 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

Sorry. That's actually a common reaction to this kind of thing, and is why Andy Clarke did that Specificity Wars thingy.

#### swa66

1:12 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Aug 7, 2003
posts:4783

Thanks, very well done.

I'm wondering just how well (if at all) the currently in active use browsers truly support this as defined in the standards.

Think I've seen one to many !important rule used as a hack to fully trust it's well supported.

#### cmarshall

1:25 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

Well, the stuff in that posting was tested on a number of fairly modern browsers, and seemed to behave consistently.

I can show you the original context, with linked examples, but I couldn't put all that here. I just spent about 15 minutes setting it up for this format and removing external links, etc.

This is part G, in a series on specificity that started with A, so there's a lot in specificity.

Thanks!

#### sgietz

6:51 pm on Apr 21, 2008 (gmt 0)

#### Full Member

joined:Jan 17, 2007
posts:306

OK, Monday morning turned to afternoon, and my brain works better now.

I did some googling and arrived at this, which would make this process much easier. I hope this URL won't get wiped from my post .. here goes:

http://www.rebelinblue.com/specificity.php

[edited by: SuzyUK at 7:29 am (utc) on May 23, 2008]
[edit reason] note: this calculator has limitations [/edit]

#### cmarshall

7:00 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

That's the critter I linked to (I took the link out the translation I did for this site).

It works, but has issues. I can get a bit "fancy pants" with CSS, and it returns garbage for a lot of my CSS.

Basically, the gist of this (and the previous six parts that preceded it) is that specificity is something we should understand, but that we won't need to go to these lengths to use. I almost never use this method. However, it's necessary in order to debug, sometimes.

Think of it as having to learn a differential equation to perform a Fourier transform, then never having to use it, because you always use FFT. Learning it was not a waste, because you understand the principles. You can solve issues and make design decisions with a better chance for success.

That Option #3 (Ju-Ju sticks) tends to be the preferred method of a large number of Web designers, because they don't actually understand specificity.

#### SuzyUK

8:10 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Oct 1, 2002
posts:5199

cm.. Nice Post - lots of thought went into that!

Thank you, am reading and digesting because you know specificity is my favourite subject ;)

First of all, I like to take into account inherited specificity (what I referred to as specificity level 1). This isn't usually accounted for in other people's calculations. It's very weak, and usually not an issue, but it does play a part, and I have been dinged by not taking it into account.

that'll be the cascade there is no such thing as inherited specificity, you can override the cascade with basic specificty .. but the basics are the cascade.. which is what cascading stylesheets are named for, so you should not write that bit off :)

[edited by: SuzyUK at 8:11 pm (utc) on April 21, 2008]

#### cmarshall

8:13 pm on Apr 21, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

that'll be the cascade there is no such thing as inherited specificity, you can override the cascade with basic specificty .. but the basics are the cascade.. which is what cascading stylesheets are named for, so you should not write that bit off!

Thanks!

I'll update my postings when I get the chance. Proper terminology is very important, especially these days, with Google and all.

Is there a more official name for inherent properties?

#### SuzyUK

8:15 pm on Apr 23, 2008 (gmt 0)

#### Senior Member

joined:Oct 1, 2002
posts:5199

they're just known as inheritable properties Chris afaik

specificity or getting specific is as you say only important if trying to override css which you don't have access to. (or at the very least understanding why LVHFA is the preferred order for links). The

``!important``
override is, IMHO, like taking a mallet to the job, it's an accessibility feature and should not be abused. It's only going to lead to compounded problems down the line if you use it your stylesheets now. It's a stop gap but should never be necessary.

I understand what you're saying about overriding CMS templates but again if it's your template it should be recoded accordingly.. imagine if the CMS theme builder built

``!importants``
into their theme :o (I know because I'm fighting with yet another Drupal Theme at the minute!)

----------
Now that I've had time to properly read your post I see the basic flaw that is likely to strike first whenever someone would come across a specificity issue (even Andy Clarke didn't get it right in his wonderfully amusing Sith Power post)

CSS Specificity is NOT calculated in base10

I know you've referred to this in your post already, but honestly it's important.. the calculator that sgietz links to and you refer to (I've put link back for this post only) also suffers the same malady. You can brush it off with the "need more than 9 parts" but with the adjacent sibling selector support these days that's not an improbability?

so (OK I was prodded! by.. you know who you are ;)) I reworked the specificity calculator now it reflects the infinite base that Eric Meyer refers to in his post and the specs also (but as usual are not patently clear about!)

It's still very likely that people will count in base10 and that's OK as most times that's enough but you know it's not quite right and so do I.

e.g. this code:

``.mytable td {color: blue;}html body table tbody tr td+td+td+td+td+td {color: red;}``

would return '11' for both elements under your method and the original calculator, effectively suggesting that the color would be red because the second rule should apply by merit of the cascade..

..however it should be 0,0,1,1 and 0,0,0,11 respectively - so despite its eleven elements the second rule is still "trumped" by the first because the one in column 'c' for the first rule beats the 0 in column c for the second despite the number in column 'd'

notation for specificity is a, b, c, d

-----------------------------

it's always been a hard subject to tackle, and I can't link anywhere but my own beta yet so here's an attempt at a rewritten CSS Specificity Calculator [suzyit.com].

I haven't tried to explain the how or why but I suppose to follow the "Malarkey" ;) what we we need is a visual hierarchy where 1 x Emperor (a) can wipe out any amount of Vaders (b)?

-Suzy

#### cmarshall

1:08 am on Apr 29, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

Suzy,

Sorry I forgot to post this earlier.

Your specificity calculator is really nice. Thanks so much. I can mention it in my pontifications if you want, but I'm not sure if you want extra links to it until you have it hammered out.

#### SuzyUK

9:26 am on May 23, 2008 (gmt 0)

#### Senior Member

joined:Oct 1, 2002
posts:5199

Chris, feel free thanks..

That link is its permanent home, I've also now hammered out some details:

rebelinblues calculator couldn't differentiate between .span and <span> or any classes/ID's that had the same name as an HTML elements, Stephen let me know this so this should now be fixed.

It now counts XML elements (except if they've a full stop/period in their actual name, while although legal, is considered bad practice?) - I don't think there's anything I can do about that as there is no way to tell if

``hello.world``
is
``element.class``
or simply an
``element``
. Hyphens underscores digits etc are OK I think.

You can maybe help I haven't allowed for the :colon which again although a legal character in an XML element is recommended not for usage as it's reserved, is that right?

Updated to reflect CSS3 properties, especially the negation selector, specificity calculations count the selectors inside the brackets but not the negation itself.

Anything else? what about the pipe character which denotes the namespace, does the element before the pipe count towards specificity?

Would appreciate some fresh eyes on it to test a few weird/wonderful combinations as I can no longer see the wood for the trees :)

-Suzy

[edited by: SuzyUK at 10:14 am (utc) on May 23, 2008]

#### cmarshall

3:15 pm on May 23, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526

Oh, I see what you mean.

Yeah, the rules should really be set forth by the W3C. I'm not aware of how we bring up these "edge" situations for some clarification. Maybe there's something on Eric Meyer's Site [meyerweb.com] (You can't get much more authoritative than him).

Thanks for the code. I may mess around with it when I get the chance. I have a lot of irons on the fire right now.

#### SuzyUK

4:53 pm on May 23, 2008 (gmt 0)

#### Senior Member

joined:Oct 1, 2002
posts:5199

think it's finished for now, just got some help in PHP which helped me tidy one part and also helped me spot another potential error if there had been multiple (nth-xx) selectors in a rule..

not too worried about the pipe separator, it's hardly a pressing issue for now and it can be very easily fixed when I know what to do with it ;)

Thanks for the code. I may mess around with it when I get the chance

Please do, and you, anyone let me know if you think it can be improved - though it's fairly short already and uses very simple clean and count logic - I'm not sure that there's much demand for it as the simple visual count is enough for most needs I would think.

But Chris, as you are into XML I thought you could help with coding practices for element names, I know what the specs say and that's what I've coded to, but I read on somewhere possibly o'reilly or a working group mailing list that usage of dots and colons within the names is considered bad coding practice.. if so it means the one wee flaw is likely not to be an issue. Of course it's not likely an issue as I don't know of anyone who would use it, I count visual too though it possibly might help if you can't instantly remember the difference between a pseudo class and a pseudo element! (that'll be me then :))

Oh well enjoy it if you need it, it's helped me with my PHP and regex's :)

-Suzy

#### cmarshall

5:11 pm on May 23, 2008 (gmt 0)

#### Senior Member

joined:Feb 21, 2005
posts: 1526