« What I should've said to the Clarion West students | Main | Mini-review: Easy A »

Overriding CSS rules with specificity

| 1 Comment

I've been using Cascading Style Sheets for years. I've created CSS stylesheets for web pages, I've written about the virtues of CSS, I've probably even written documentation about it.

But sometimes I run into roadblocks, where no matter what I do, I can't get a particular CSS rule to work.

The most common situation where that happens is that I've set a style for something, and then I try to unset or otherwise override that style for a special case. For example, in my current blog stylesheet, I indent paragraphs, but I wanted the first paragraph after a heading to remain unindented.

So I added a new rule, near the end of my blog's stylesheet, that looked like this:

h2 + p
{
  text-indent: 0em;
}

Simple, straightforward, clear rule. Should work.

But it didn't.

After much pounding my head against this, and a fair tad bit of online research, I concluded that there must be something going on with CSS precedence that I didn't know about. Because I always thought that CSS precedence was a combination of things like origin (author, user, or browser) with linear order in the file, so I thought that a CSS rule defined near the end of my main CSS file ought to override anything that came before it.

Turns out: not always. I knew about rules 1, 2, and 4 of the CSS cascade, but I didn't know about rule 3; turns out that CSS precedence also depends on something called specificity.

The short version of that confusingly written section of the CSS spec is that the number of various kinds of items in the CSS selector determines how specific the rule is, and thus which rule takes precedence.

Simple CSS selectors tend to consist of only a single ID, class, or HTML element name; specificity is straightforward for those, so cascades for simple selectors usually work the way we expect. Which is why I never knew about specificity before.

But when you start specifying more complicated selectors, like .asset-body h2 + p, specificity starts becoming a little trickier.

So now I know: if a rule is mysteriously failing to override an earlier rule, it may be because the later rule isn't as specific; one way to resolve that issue is to make the later rule more specific.

It would be cool if various authoring tools and CSS-debugging tools were to foreground specificity as an issue (and, more generally, to give better explanations of why a given rule is or isn't in effect at a given point); I suspect knowing about this would've saved me a lot of frustrating hours over the past few years.

1 Comment

Try using the Developer Tools in Google Chrome, it will let you see which rules are applied or ignored, can edit the HTML and CSS live on the page, and it's easier to identify CSS woes - which are very easy to fall into.


Post a comment