CSS Is A Lie.

According to Wikipedia:

Cascading Style Sheets (CSS) is a style sheet language used to describe the presentation semantics (the look and formatting) of a document written in a markup language.

Furthermore:

CSS specifies a priority scheme to determine which style rules apply if more than one rule matches against a particular element. In this so-called cascade, priorities or weights are calculated and assigned to rules, so that the results are predictable.

From my informal office survey, the general consensus is that the most important thing™ in CSS is that everything ‘cascades’ correctly. That is, that rules and styles defined further down in a CSS document override styles specified further up in the document (excluding the !important operator of course, which you should not be using anyways). It makes sense if you think about it, after all it’s not called a Cascading Style Sheet for nothing.

Now, the test. Given the following HTML and CSS snippet, what color will the two paragraphs be?

HTML

<p id="myid" class="myclass">
   Hello World.
</p>
 
<p class="myclass">
   This is another line of text
</p>

CSS

#myid {
   color: red;
}
 
.myclass {
   color: blue;
}
 
p {
   color: green;
}

The Answer:
Hello World is red, the second line of text is blue.

Don’t believe me? I put up a demo page with just the html and css here.

After a decent amount of Googling and reading blogs and the W3C Spec on CSS Selectors, I realize now how styles are calculated and applied, but seems to go completely against the ‘cascading’ nature of style sheets since the cascading nature of style sheets only applies when the ‘specificity’ values are the same.

For example, the following snippet behaves as you would expect:

CSS

p {
   color: gray;
   font-size: 20px;
}
 
/* ... later ... */
 
p {
   color: green;
}

As you might expect the paragraph will be green, and have a font size of 20px. The rule that is more specific selectors takes precedence over rules that are less specific regardless of where that rule is declared in the markup. You can mentally calculate how specific a rule by the ‘level’ and number of the selectors used. From low to high, you have

  1. Element and pseudo elements such as p, a, span, div, :first-line
  2. Class, attributes, pseudo-classes .myclass
  3. Id attributes #myelement #theonething
  4. From inline style attributes
  5. !important

If there’s anything of a higher level, the higher level overrides the lower level style, and if they’re the same level, the higher count wins, and if they’re at the same level with the same count (.myclass, and .myotherclass) then the one further down takes precedence, this is the “only” time cascading actually happens.

Its something that is unfortunately very subtle because of the way we write CSS, your taught from the begin to start with the most basic generic styles and work your way through the more specific styles. While this is correct, it’s very easy to go for a long time without running into a situation where a more specific styles.

I had no idea up until about a week ago that CSS worked like this. I always assumed that specificity was only used to select the subset of elements the rule applied to, and that if you applied a more general rule after a more specific rule that the more general rule would overwrite anything earlier. This is obviously not the case. If you want to read more, here’s some links to a few more comprehensive articles on the subject:

CSS Specificity and Inheritance: http://coding.smashingmagazine.com/2010/04/07/css-specificity-and-inheritance/

Star Wars and CSS Specificity: http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Specifics on CSS Specificity: http://css-tricks.com/855-specifics-on-css-specificity/

Art and Zen of CSS: http://donttrustthisguy.com/2010/03/07/the-art-and-zen-of-writing-css/

One thought on “CSS Is A Lie.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>