How to deal with CSS browser differences

The problem

If you've been using CSS for some time now, you have probably been spending a lot of time trying to make it work in all browsers. Indeed, this is the reason why CSS and XHTML have not been widely adopted and many people still use a table layout.

Why this difference?

Firstly, let's recognize all browsers have bugs, although some more than others. In fact, it's likely you will stumble upon at least one such bug for every site you design.

Secondly, IE does not fully implement the CSS 2.1 specifications, so it will not understand fancy (but very useful) CSS like:
li:hover – might be used for a drop-down menu
input:focus – might be used to change the color of a text input when the user is typing in it
tr > td:first-child – might be used to change the color of the first column of a table

Thirdly, IE5 uses a different box model than all the other browsers. The padding of an element is not added to the width, but is instead part of it. It also does other nasty things. For instance, it won't center a division if you do this div.your_class{margin:0 auto;} (every other browser does).

The solution: the CSS separation method

Separating the CSS

While this method does not cure the problem itself, it does make it easier to deal with it, by separating the CSS into two or more files.

First of all, let us recognize that IE is the source of most of our problems. Hence it makes sense to create one CSS for everyone, and another specially for IE.

So instead of going through all the troubles of making one CSS work in all browsers and often ends up looking like this ...

	/*** Fix IE bug ***/
	div.fix { blah blah

	/*** Fix Firefox problem caused by the previous fix ***/
	body > div.fix { blah blah
	

... you will have different CSS files. The first file is the 'good' CSS, that is always sent to the browser. The second simply redefines all the properties that are causing trouble in IE, and gets served only to IE.

How does it work? This is called conditional commenting. IE sees the new CSS file and uses it, whereas other browsers just ignore the whole thing as if it were a usual comment.

<!--[if IE]><style type="text/css">@import "ie_fixes.css";</style><![endif]-->
	

You can replace [if IE] with [if IE 6] (or any other version) so that only IE 6 will use the CSS. You can also use [if lt IE 6] to match browsers of versions lower than 6 (or gt for greater than).

It is actually a bad idea to finish a site and only then start creating the ie_fixes.css file, because it will not be very clear where the problems come from. You should fix each problem in the ie_fixes.css file when it arises rather than let them build up.

The complete code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
	<title>Page title</title>

	<link rel='stylesheet' type='text/css' href='normal.css' />
	<!--[if IE]><style type="text/css">@import "ie_fixes.css";</style><![endif]-->

</head>

You can see this in action at Wikipedia or at this very site.

More Information

Actually making the two CSS files work in their intended browsers is beyond the scope of this article, but here is some basic advice.

When you run into a problem

If you are not very experienced with CSS, the first thing to do when you run into a problem is to validate your CSS at: http://jigsaw.w3.org/css-validator/

This is to ensure there are no problems with the CSS itself. Fix any errors or warnings the validator has found. Note that a valid CSS is not necessarily a good CSS. Check out the W3C CSS specifications if in doubt.

Also, you should check your (X)HTML for validity at: http://validator.w3.org. Note that if you properly declare XHTML as application/xhtml+xml and open the document with an XHTML-supporting browser you will have automatically checked it for well-formedness.

A browser specific behavior

This is the least of your problems.

All browsers display XHTML elements by default in slightly different ways.

Make sure you specifically set the property that is causing the problem in your CSS. For example, set a padding and margin for all the elements (to 0 if it should be 0), including the body element. Otherwise browsers will use their own default values.

A browser bug

Fortunately, there are many ways you can do something in CSS.

The way to deal with a bug is to do things differently. Use your imagination to come up with alternatives. Use margin instead of padding, use absolute instead of relative positioning, etc.