Stylist Logo

The “Scientific” Method

This entry is part 9 of 15 in the series Stylist

ABSTRACT

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.
  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.

THE BASICS

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, 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. It was written by the folks who wrote the standard. 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 cascaded specificity (what I referred to as specificity level 1 -inherited from enclosing elements). 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. cascaded Specificity from an enclosing element is Just Plain 1 (Exponent 0) (NOTE: CSS pseudo-classes add 1 to this lowest value (for example: a:visited, or a:hover). This is how a hover pseudo-class can override the base rule. I don’t use pseudo-classes that often, because of very inconsistent browser support.)
  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. I don’t use these much, and prefer using my brain and eyeballs.

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:

Example 49

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>

We’ll start with the lower specificities.

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

We add them together:

1240

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

Example 50

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 }

Example 51

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 }

Example 52

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 }

Example 53

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 your browser’s element inspector, 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“.

Example 54

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

Inherent always beats cascaded, but nothing else. It is the same specificity level of cascaded, 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:

Example 55

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.

Example 56

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:

Example 57

<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:

Example 58

<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:

Example 59

<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:

Example 60

<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:

Example 61

<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>

THIS JUST IN: According to Eric Meyer, who is one of the originators of the CSS standard, the most common nomenclature for specificity is 4 numbers, separated by commas (as noted in the CSS specification). This is a, b, c, d, where a is inline style (style=""), b is ID (id=""), c is class (class=""), and d is implicit (tag/element name).

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. 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 the additional CSS for this site, 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.