Internet Explorer (IE), version 9 and older, is notorious for its aberrant rendering of CSS. Fortunately, there are no less than six methods to correct that, varying from generic & easy to specific & complicated.

One method and a sub method rely on code that will not pass the CSS validation test newWindow (1K). Personally, I don't care much about that test, because it often judges perfectly working and semantically correct CSS lines as invalid. Thereby limiting the number of tools that web developers have (see later).

Valid HTML is important, very important even, because if invalid it often causes problems (go check newWindow (1K) your code for errors now...). With CSS, it quite frequently is the other way around when it comes to the graphic possibilities. But you might have a reason why you want the CSS to validate, too, so I will tell you what to avoid.

I assume that you have a basic knowledge of HTML and CSS. If you don't, you should do a beginners courses at for example W3 Schools newWindow (1K). That's a decent site when it comes to accuracy and completeness, and an excellent site didactically speaking.

The six methods are these:

  1. A standards mode-forcing doctype.
  2. Addressing the use of new HTML5 tags.
  3. A CSS reset.
  4. CSS hacks.
  5. The <html> conditional class method.
  6. Conditional style sheets or blocks.

1. A standards mode-forcing doctype

The starting method to correct IE problems is to make your HTML code force all browsers to use at least the same box model newWindow (1K). To make all browsers, including IE6, use the W3 box model, simply have a(n almost) standards mode-forcing doctype tag to be the very first HTML line of your code.

Not even an HTML comment may precede it. Only PHP lines and the likes may, because those are processed by the server and removed before releasing the page to the visitor's browser.

There are several doctypes, all with their pros and cons, which you can all find here newWindow (1K). These two are probably the ones that you will want to use, because they are flexible, force a sufficient standards mode and can easily be combined with the fourth correction method:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

<!DOCTYPE html>

If you are going to use an iframe and want it borderless, or don't know know how to make IE6-8 support the new HTML5 tags, you should use the 4.01 Transitional doctype. However, be aware that without the W3 URL, the so-called system identifier, the Transitional type will put all browsers in quirks mode. That also counts for having no doctype at all.

In that mode, IE6-8 will use the traditional box model while all other browsers use the W3 model — voilá, the most prevalent cause of rendering differences. If, for whatever reason, your want or are forced to maintain the quirks mode, you can still have all browser apply the same — traditional — box model. Simply include this in your CSS:

* {
    -moz-box-sizing: border-box;    /* older FF */
    -webkit-box-sizing: border-box; /* older Safari/Chrome */
    -o-box-sizing: border-box;      /* older Opera */
    box-sizing: border-box;         /* new browsers */

Do not do both, because IE7 does not support box-sizing. Also, this code will not validate, due to the older-versions-targeting properties (see later). Nonetheless, the doctype or box-sizing method quite often already solves the rendering problems. If it doesn't, go on to one the following methods.

2. Addressing the use of new HTML5 tags

Although the HTML5 doctype in itself is rendered as far back as IE6, believe it or not, a correct rendering of its new tags needs IE9 or later. Examples of those new tags are <header>, <nav>, <section>, <article>, <aside> and <footer>.

The remedy is to change the new tags back to <div> tags. As this is a tutorial on CSS methods, this option is mentioned first. However, because that could mean a whole lot of work if the site consists of many pages, the following option should be mentioned as well: include a javascript newWindow (1K) that upgrades IE<9 in that aspect.

3. A CSS reset

This makes all browsers start with the same set of CSS base rules. There is Eric Meyer's comprehensive method newWindow (1K), but I think that is unnecessarily complicated/long. Also, you probably have already included the HTML5 lines if that is your doctype. And Eric forgot to include font-size-adjust and letter-spacing [was: font-stretch; corrected].

Also because browsers simply ignore non-applicable CSS code, and because it is 100% valid, the code can therefore be as simple as this:

* {
    margin: 0;
    padding: 0;
    border: 0;
    font: inherit;
    font-size: 100%;
    font-size-adjust: none;
    letter-spacing: normal;     /* see remark in text */
    vertical-align: middle;
    border-collapse: collapse;
    border-spacing: 0;
    list-style: none;           /* esthetic only */
    quotes: none;
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;

Do note that you will have to check your whole site when doing a reset, because it may change the rendering of quite a few matters, as you can imagine. And of course, the reset should come before all other CSS declarations. You might miss the line-height, but it is no use setting that to a particular value, because all elements need different ones. Instead, you should declare the line-height for all applicable elements separately, like in this shorthand:

body {
    font: 0.8em/1.4em Verdana; /* line-height is second */

4. CSS hacks

'Hacks' is a greatly exaggerated term, because the code lines do nothing harmful to your computer or browser — they just make the CSS not pass the validity test. With thanks to Dimox newWindow (1K) for the IE8 only and the IE10 method, they look like this if applied to an unordered list:

ul { color: green; }         /* in every other browser */
ul { *color: pink; }         /* IE7 (and 6) */
ul { color: orange\0; }      /* IE8+9  */
@media \0screen {
    ul {color: purple;}
    }                        /* IE8 only */
:root ul { color: blue\0; }  /* IE9 only */
@media screen and (-ms-high-contrast: active),
(-ms-high-contrast: none) {
    ul {color: yellow;}
    }                        /* IE10 */

I have tested them all, except IE10. Here is a simplified test file newWindow (1K). If you are able to test it in IE10, or would still find any errors in other browsers, please let me know (see the footer section for my address).

5. The <html> conditional class method

This technique was invented first by Nikhil Kothari newWindow (1K), reinvented/made popular by Paul Irish newWindow (1K), 'put on steroids' by Patrick O'Neill newWindow (1K), simplified a bit by me and goes like this: replace the <html> tag with this code block:

<!--[if IE 6]> <html class="ie6 lte7 lte8 lte9"> <![endif]-->
<!--[if IE 7]> <html class="ie7 lte7 lte8 lte9"> <![endif]-->
<!--[if IE 8]> <html class="ie8 lte8 lte9"> <![endif]-->
<!--[if IE 9]> <html class="ie9 lte9"> <![endif]-->
<!--[if !(IE)]><!--> <html> <!--<![endif]-->

I assume that you are familiar with the HTML comment
<!-- blabla -->
and the IE conditional comment
<!--[if IE 7]> blabla <![endif]-->
and will understand that classes are assigned conditionally. (If not, have a look here newWindow (1K).) Then, targetting one or more IE versions is simply a matter of adding the applicable class(es) to your CSS. Like this for example:

div#header { width: 600px; }
.lte7 div#header { width: 602px; } /* IE6 and 7 */

The lte in lte7 stands for: less then or equal to IE7. You might think that lte6 is missing from the first conditional comment, but IE6 alone can also be targeted by using the ie6 class, and you won't be coding for lower than IE6.

Boilerplate has/had this as last comment line:
<!--[if (gt IE 9)|!(IE)]><!--> <html> <!--<![endif]-->
but that doesn't make sense because IE10 does not support conditional comments anymore. For that same reason, it is no longer useful to include a separate IE class in the comment — just use lte9 if you want to target all IE versions older than 10.

Adding conditional classes with javascript

That is done by including this javascript newWindow (1K) in the head. You can even include it in an already existing head or body javascript, which should come in handy if you have to make changes to a number of existing pages. Also, as you will see, you can target other browsers than IE as well with that script.

6. Conditional style sheets or blocks

Such style sheets or blocks are invoked by conditional comments as well, in this way (sheets):

<!--[if IE]><link rel="stylesheet"
href="url-of-ie-sheet.css" type="text/css" /><![endif]-->

or this way (blocks):

<!--[if IE]>
<style type="text/css">
selector {
    property: value;

If you are going to use the style sheet method, make sure that the conditional link tag comes after the normal tag. Latter style sheets overrule earlier ones.

Change log
V. 1.1: added CSS reset method for problems with other browsers.
V. 2.0: integrated the doctype inclusion and CSS reset as IE methods rather than a remark/method for other browsers. Improved CSS reset code. Simplified the <html> conditional class section.
V. 2.1: added the method of changing new HTML5 tags back to div tags, for IE<9.
V. 2.2: added javascript method of adding conditional classes.

I am Frank Conijn, a web designer and author from Amsterdam, the Netherlands. At the moment, I am too busy with other web projects to be making websites for others, but I am available if you want to hire me for problem solving or advice. Just mail me at

Was this article helpful and do you have any Google account? A Google recommendation of my business, by means of simply clicking this button, is appreciated:

For general comments on and suggestions for this article, mail met at the above address. For free help with minor problems, post your question on one of these web design forums (pop-up).