Zombies Fill the Specific Ocean
You know something about websites, do you? Already conquered that “HTML” thang, huh? Got a grasp on CSS? Good. Well did you know that a properly formed website could beat the unliving tar out of a horde of the undead? Did you know that websites accounted for ninety-seven percent of zombie second-deaths in the last twenty-two years? You find that hard to believe? Well, let me drop some knowledge on your finely-combed head. We’re at war and you are our last hope to stave off the apocalypse. Now let’s take down some zombies.
(If you don’t have the basics down on HTML or CSS you’d probably get more out of the book if you know them well. Two resources you can use that also include zombies are A Beginner's Guide to Learning HTML (and Smacking Zombies Upside the Head) and Basic CSS: Like Putting Lipstick on a Zombie)
Zombies Fill the Specific Ocean
When a browser has competing and contradictory CSS rules, it uses the process of specificity to determine which rule to follow. (If the rules have properties that don't contradict each other, then both will be applied). It's the cage match from which only one CSS property will survive.
Closer to the Content
Generally, the closer to the content, the more likely a rule will beat out another rule of the same specificity. So a browser’s default style sheet will be beaten by an external style sheet, which will, in turn, be beaten by CSS rules in a style tag, which will be beaten by CSS rules in a style attribute. With each successive placement, we get closer and closer to the content. Within each placement, the CSS rules further down, being closer to the content, will override other rules of the same specificity that select the same element.
One other important piece is that an inline style will win out over almost everything else, even with the highly specific selectors we’ll be talking about next. The style tag is actually on the element you wish to apply it to. How much more specific can you get?
The Cage Match
In any given web page, there are usually hundreds, if not thousands, of HTML elements. Applying CSS to them individually would be an apocalyptic mess. Luckily we have a few tools in our tool belt. The handiest ones are element selectors, class selectors, id selectors, and descendant selectors.
As we go down that list, we get more specific. There are often a lot of paragraph elements on a page, but there are probably only a few with a class of talkin-smack, and, since there can only be one with an id of zombie-kills, that id will be much more specific than either an element or a class. The more specific you are about which element you're trying to select, the more likely those rules will win out in the specificity cage match.
Now, descendant selectors are a sum of the specificity of their parts. The best way to explain a descendant selector’s specificity is to imagine that each type of selector is worth a set of points. Elements are one point, classes are ten, and ids are a hundred points. Add them together to figure out their specificity
#zombie-killa p a { color: black; } .talkin-smack div .verbal a { color: red; }
If both of these selectors were selecting the same element, what color would the link be?
#zombie-killa (id=100) + p (element=1) + a (element=1) = 102 .talkin-smack (class=10) + div (element=1) + .verbal (class=10) + a (element=1) = 22
The link will be black.
Here's another:
#zombie-killa .talkin-smack a { color: black; } #zombie-killa div .verbal a { color: red; }
#zombie-killa .talkin-smack a = 111 #zombie-killa div .verbal a = 112
The link will be red.
When you need to increase the specificity of a selector but don't want to add elements or otherwise change the selector much, you can include the class and/or multiple classes from the element by leaving out the space before the class name(s). For example, if talkin-smack were on a div and that div also had the class ima, it would be written as:
div.ima.talkin-smack
Thus the following construction would make the text black:
#zombie-killa div.ima.talkin-smack a { color: black; } #zombie-killa div .verbal a { color: red; }
#zombie-killa div.ima.talkin-smack a = 122 #zombie-killa div .verbal a = 112
Night of the living tip:
If we’d only added the element, the lower rule would still have applied, since they would have been equal and the lower rule would be closer to the content. We could have just added the ima class to overrule the second rule, but then you wouldn’t have seen an example of using elements in this way.
There's one big caveat to the 100s/10s/1s calculation. Mathematically, a selector with ten classes should be as specific as an id and a selector with ten elements should be as specific as a class selector, but this is where the analogy breaks down. A single class will beat out ten, a hundred, or even a thousand element selectors. Similarly, an id will beat out any number of classes.
Use IDs Carefully
While ids are great tools, they should be used sparingly to decide specificity squabbles. If you fight a zombie with a club, it might come back with a knife. Then you bring a metal bat and they bring a gun. You bring a Gatling gun; they infiltrate your hideout and take your sister hostage. You mount a daring rescue mission to get her back, only to find that she's been turned and that you have to nuke the whole stinkin’ nest. As the mushroom cloud goes up, removing one more livable area from the planet, you wonder how this all started and where it went wrong.
When you escalate specificity, you’ll have to learn more and more tricks to override it further down the line. So use ids and the next tool sparingly and carefully.
Overruled!
Besides moving a CSS rule closer to the content to beat out similarly specific rules, you can also add !important to the end of the rule between the value and the semicolon.
#zombie-killa div.ima.talkin-smack a { color: black; }
#zombie-killa div .verbal a { color: red !important; }
!important is the specificity trump card. It’s the only thing that will beat out an inline style. It's particularly useful when you have styles applied from a third-party module, plug-in, or framework, as you’ll be bound by the choices those developers made. They probably didn't foresee your use case, and you’ll need to override their styles for a certain piece. This can cause difficult specificity problems, for which !important may be the best choice.
But with great power comes great opportunity for misuse. Whenever possible, use something other than !important to win the specificity battle because you have no weapons left except for rewriting the style sheet if you need to override the !important rule. If you use the nuke and the nuke doesn't work, what options are left?
No specificity
The all selector or * has no specificity because it applies to all elements. The same is true for any selector operators (such as + or >, which we’ll discuss these later). They have no specificity in and of themselves, but the elements that they connect do. If you have two rules with the same specificity except for a combinator, make sure that the one with the operator is last. Otherwise, it'll never apply.
Pseudos
We’ll discuss these more in the next sections, but pseudo classes and pseudo elements have the same specificity as their namesakes (i.e., pseudo classes have class-level specificity, and pseudo elements have element specificity.)
Try it Out:
Codepen demo:
So now that we've covered the rules of specificity, I bet you could spout off which CSS rule should apply, even when a zombie is moaning in your ear—right?