Deprecated Behaviour

The inane, sometimes insane, ramblings from the mind of Brenton Alker.

Priority When Multiple CSS Classes Are Applied

I’ve used multiple CSS classes applied to an element on many occasion, but never run into the problem I found today. It seems counter to the CSS system as I understand it, but I’ve checked it out and it works like this.

I had a page, who’s table cells all had a CSS class that applied a background colour, some font attributes and what have you. The class (from an external stylesheet file):

1
2
3
4
5
6
7
td.listCell
{
    color: black;
    background-color: grey;
}

was applied individually to each cell like:

1
<td class="listCell"></td>

I needed to apply a second class on certain cells to change the background colour, this is part of an on-page Javascript search. This page has lots of content, a large form, most of which is hidden and only small parts are used at a time. The search is supposed to highlight the cells that contain the text in the search field.

So, I added a searchHighlight style to the head of the page, making it look like:

1
2
3
4
5
6
7
<head>
    <style type="text/css">
        .searchHighlight { background-color: red }
    </style>
    <link rel="stylesheet" type="text/css" href="stylesheet.css" />
</head>

On my way I went, coded the javascript to search the table and add the ‘searchHighlight’ class to the cells that needed hightlighting. Easy. Except it didn’t work.

When the Javascript found it’s target, and changed the class (by appending searchHighlight to the className) nothing happened. I checked the Javascript had worked, using my trusty FireBug source inspector. It had. So why no change in the style?

I changed the Javascript to replace (instead of append) the searchHighlight class, that worked, except it lost all it’s normal formatting, which I was almost willing to put up with, but not quite. I tried pre-pending the searchHighlight class (hoping the styles were in priority order), but to no avail.

So I created a simple test page, to make sure I was wasn’t going (more) insane, and that multiple CSS styles ever worked. The test page looked like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <title>Multiple CSS Class Test</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
        <style type="text/css">
            .normal { font-weight: bold; background-color: red;}
            .special { background-color: blue }
        </style>
    </head>
    <body>
        <div class="normal">class="normal"</div>
        <div class="special">class="special"</div>
        <div class="normal special">class="normal special"</div>
        <div class="special normal">class="special normal"</div>
    </body>
</html>

The results are sort of what I expected… the top div (normal) is red and bold, the second (special) is blue and not bold, the other two are applying both, but the order of the classes in the list doesn’t matter. So they are getting the bold from the normal style, and the background from the special style.

Great. So why didn’t it work in my application? I finally figured it out. If, in my test, I reversed the order of the declaration of the styles (so that ‘special’ is declared first) and the results are very different, the ‘special’ class is ignored completely.

That’s right, the styles are applied in the order they are declared in the document, the order they are listed in the element has no effect. That I now understand (although I didn’t know it previously). But what I find more suprising, is that the order of stylesheets files that are linked is also subjected to this hierachy.

For example, if (from my test page) I remove the special style, and put it in an external style sheet, and include it like so:

1
2
3
4
5
6
<style type="text/css">
        .normal { font-weight: bold; background-color: red;}
</style>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />

It works, but doing this doesn’t:

1
2
3
4
5
6
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<style type="text/css">
        .normal { font-weight: bold; background-color: red;}
</style>

So the include is exactly the same as typing in the style in the file. Whereas I was under the impression that styles in the file took precedence over those in external (linked) stylesheets (where they overlap of course). But it seems I was wrong. Now I know.