Dojo's cross-browser css solution and how to use it

Level: Introductory
Date: Originally posted 3/08, updated 4/08.
Author: Richard Bondi,

It's old news that browsers interpret css differently, and that there is no one way best way to deal with this exasperating problem. This post explains Dojo's mechanism for writing browser-specific css, which is currently undocumented.

Step 1: Get Dojo to add to your BODY's class attribute

If your html page doesn't do this already, add to it either:
<script type="text/javascript" src="dojotoolkit/dojo/_base.js"></script>
or:
<script type="text/javascript">
  dojo.require("dijit._base.sniff");
</script>
Once the page has loaded, this will use Javascript to add an extra css class name to your BODY's class attribute. For example, let's assume your html page contained <BODY class="foo">. When that page is loaded in Safari, <BODY class="foo"> wil become <BODY class="foo dj_safari">.

Step 2: Touch up your css classes for each badly behaved browser

Imagine you have a css file mycss.css, and in it the classes .foo and .bar work fine in every browser except Safari. Maybe they look like this:

[File: mycss.css]
.foo { border:1px solid black; margin: 0px}
.bar { margin-top: 0px; width:'2em'; }

In this css file, after the above classes, add some new "touch-up" css to make Safari behave like all the other browsers:

[File: mycss.css]
.foo { border:1px solid black; margin: 0px}
.bar { margin-top: 0px; width:'2em'; }
.dj_safari .foo {border:2px solid black; margin: auto; }
.dj_safari .bar {margin-top:auto; width:auto; }
Here ".dj_safari .foo" means "Match any element with (i) a css class named 'foo', and (ii) which is a descendant of an element with a class named 'dj_safari'."

Well, in Safari, every element will be the descendant of an element with a class dj_safari, because every element is a descendant of <BODY class="foo dj_safari">, thanks to Step 1.

In your mycss.css file, as long as you place ".dj_safari .foo" after ".foo" in the css file, any css in ".dj_safari .foo" will override matching css commands in ".foo". In other words, you can have different css for Safari, and thanks to step 1, it will only take effect when the page is loaded in Safari.

In other browsers, there will never be an element with a css class named "dj_safari", so the lines in mycss.css that begin with ".dj_safari" will be ignored.

And that's the trick.

This simplifies cross-browser css enormously. All you have to do is make "touch up" css using the magic Dojo class names named for browsers. Where are they? Uh, they're undocumented (as is this everything else in this article). However, you can find them all listed in the file sniff.js, in this code block:

[File: sniff.js]
var classes = {
        dj_ie: ie,
//        dj_ie55: ie == 5.5,
        dj_ie6: maj(ie) == 6,
        dj_ie7: maj(ie) == 7,
        dj_iequirks: ie && d.isQuirks,
// NOTE: Opera not supported by dijit
        dj_opera: opera,
        dj_opera8: maj(opera) == 8,
        dj_opera9: maj(opera) == 9,
        dj_khtml: d.isKhtml,
        dj_safari: d.isSafari,
        dj_gecko: d.isMozilla
    }; // no dojo unsupported browsers

The file sniff.js also contains the code that carries out Step 1 above.

Use with Caution

In our example, the file mycss.css is downloaded by all browsers, not just Safari: even non-Safari browsers have to download the "touch-up" css. Ideally, you should only need a little extra cross-browser css. For example, the mail.css for Dojo's mail demo contains only this smidgen of it:

[File: mail.css]
.dj_ie6 .mailIconCancel,
.dj_ie6 .mailIconOptions,
.dj_ie6 .mailIconFolderDocuments,
.dj_ie6 .mailIconFolderInbox,
.dj_ie6 .mailIconFolderSent,
.dj_ie6 .mailIconGetMail,
.dj_ie6 .mailIconNewMessage,
.dj_ie6 .mailIconMailbox,
.dj_ie6 .mailIconOk,
.dj_ie6 .mailIconTrashcanFull {
    background-image: url('icons.gif');
}

But you can't always hope to be so lucky: dijit.css contains 47 extra css "touch-ups."

The moral: use this cross-browser css dojo trick with care, and as sparingly as possible.



Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.