CSS Inheritance

So yes, there has been a long delay from the last time I blogged, but I thought I would come back with something that I have actually been asked a lot about recently, which is CSS Inheritance.

I'm finding out that front end technologies are like Sanskrit to many server side developers, which is strange, because CSS and Javascript, to me, are easier to understand.

But issues like inheritance in CSS (and OOP in Javascript) break convention so much that it's hard carrying over knowledge of the server side to the front end.

Many people assume that inheritance is controlled by a few factors, one of them being source order. And, it's true, that all things being equal, the last line of code in the source takes precedence.

But that's assuming all things are equal, which, as we'll see, is not often the case.

Let's take a look. Assuming that we have a body tag like this: <body class="my-class">, and this CSS in our file:

body.my-class { background: #000; }
.my-class { background: #f00; }

What color will the background be? Most people might assume that it's #f00 (red). But alas, it is not.

The background color of the body would be black (#000). Why? Because of one of the more confusing (but powerful) features of CSS, and that is CSS Specificity.

The idea behind it is that the more specific your selector, the more precedence it's going to have.

So what about a code setup like this:

<body class="my-class" id="myId">

and CSS like so:

#myId { background: #000; }
html > body.my-class { background: #f00; }

Again, the body background color would be black. Confused yet?

The reason is because each piece of the selector has a given weight, but they're not all equal. Each selector is actually a calculation of it's pieces weight, so that every selector has a certain number of points.

This is news to most people, but it's true. Each selector has browser given weight to it, and if you add the points up, you can tell which selector will win out.
So what are the points?

Elements (li, p, a, table, etc) all have 1 point.
Classes (.my-class, .banner, etc) all have 10 points.
Psuedo classes and attribute selectors (:link, :hover, :focus, [rel=external], [type=text]) all have 10 points
ID's (#myId, #wrapper, etc) all have 100 points
Inline styles (style="background: #0c0;") all have 1000 points.

So if you want to calculate why a certain style isn't getting applied, some quick math, you would see that a setup like this:

a[rel=external].my-class { background: #f00; }
a.my-class { background: #0c0; }

Would result in a red background (#f00) because of the points.
In the first selector we get 1 point for a, 10 points for [rel=external], and 10 points for .my-class for a total of 21 points.
In the second selector, we get 1 point for a, and 10 points for .my-class, so 11 points for that selector.

But, the confusion doesn't end there. There are some caveats.
For instance, an ID, even though only containing 100 points, will win out even over a selector with a point value greater than 100 points.

So an ID always has precendence over all other selectors, except if there is another ID in that selector. And an inline style will always win out over an ID, even if there is a 100 id's in the selector.

Now, to pile on the confusion even more, you can give weight toa certain property that will always be obeyed, no matter where the  selector is defined.
You would do that with !important.

Here's how it would work:
body { background: #fff !important; }
body#myId { background: #f00; }

The body would get a background color of #fff, even if there is an inline style, or some other heavy selector. 2 caveats, however.

1. This doesn't work in IE 6.
2. This can cause problems in styling and should only be used in rare cases.

Personally, it's stuff like CSS specificity and inheritance that cause confusion, and keep people from using the full power of CSS to their advantage.

 

 

Blogs
Um, wow. Now I understand why I've spent hours of frustration pulling my hair out with CSS problems. Not that that isn't going to change, but you've helped a lot.

And I've seen !important before, but like a typical server side developer, I thought it meant "not important." :-)
<img src="http://cdn.www.liferay.com/image/image_gallery?img_id=338842" width="400" height="120" alt="The ability to destroy a planet is insignificant to the power of the !IMPORTANT...">