Cascading Style Sheet Compatibility in Internet Explorer 7

Markus Mielke
Dave Massy
Microsoft Corporation

January 31, 2006

Updated September 26, 2006

Introduction

Internet Explorer 7 contains a number of improvements to cascading style sheet (CSS) parsing and rendering over IE6. These improvements are aimed at improving the consistency of how Internet Explorer interprets cascading style sheets as recommended by the W3C in order that developers have a reliable set of functionality on which to rely.

In some cases a few of these changes may have the effect of making existing content render in ways that are not compatible with IE6. This is often seen with elements moving to a different area of the page or overlapping content when viewed in IE7. These issues are most common on content that is using particular CSS constructs (often know as "hacks" or filters) to work around bugs that existed under the strict mode in IE6. In this article we'll discuss why pages might be broken due to updated CSS support and the best ways to address the issues that result from it.

Taking Compatibility Seriously

On the Internet Explorer team we consider compatibility to be an essential part of delivering a platform on which developers can build great solutions. We need to continue to display existing content in newer versions of the browser while at the same time adding improvements and new functionality. In order to address these seemingly conflicting goals we have what we loosely refer to as quirks and strict mode when interpreting content. Support for strict mode was introduced in Internet Explorer 6 and is determined by a declaration at the start of the HTML page. In quirks mode, we ensure compatibility so that existing content continues to render as it did in previous versions of IE. By contrast, in strict mode we work towards improved conformance with W3C recommendations, which may include changes that affect existing content.

Many of the issues around CSS parsing and display present in Internet Explorer 6 are well documented on sites such as www.quirksmode.org and www.positioniseverything.net.

In the case of CSS used for IE, we believe we are making the right decision by fixing bugs present in IE6 under strict mode even when this results in a change in rendering for pages.

Addressing Broken Pages in IE7

If a page is rendering differently in Internet Explorer 7 than in previous versions of IE then the first step is to diagnose the cause of the problem so that we can address it in the most efficient manner possible.

User Agent Strings and Browser Detection

Before looking at the effects of CSS changes in IE7 we should eliminate another common compatibility issue. Some sites serve different content based on the type and version of the browser that is being used to access them and are not expecting to be accessed by IE7. This is known as User Agent String detection and more details can be found at Detecting Internet Explorer More Effectively.

XML Prolog Bug Affecting the CSS Box Model

The XML prolog is intended to specify the version of XML being used and is mostly seen on the Web in conjunction with XHTML. As explained above, in IE6 we introduced a method to switch between quirks and strict mode. This switch had to be the first line of a page. Sadly the XML prolog required the same and most authors using the XML prolog would add it before the strict type switch. This caused IE6 to ignore the author's intention and IE6 would render the page in quirks mode rather than strict. We fixed this issue in IE7. Now, you can have the XML prolog and immediately follow the strict mode switch to render XHTML properly. Sadly some pages build their content with the assumption that IE is not in strict mode (even though IE should according to the HTML spec). Rendering issues caused by the XML prolog fix can easily be identified: Open the view-source looking at the first two lines of the page. If you see the XML prolog and a strict <!DOCTYPE> and the page has rendering issues, it is most likely that the page author needs to update the content.

Box Model Changes

In IE7, we changed the behavior of overflow to align with the CSS2.1 box model. Overflow is describes as a method to specify whether content of a block-level element is clipped when it overflows the box. The default is visible. This value (visible) indicates that content is not clipped, i.e. it may be rendered outside the box. IE in the past did not support this behavior. Content always had to fit within a box dimensions. Imagine a box with width and height of 100px. If the content is smaller than 100px then IE would follow the specifications. If the content exceeded the size we would auto-grow the box to fit the content. To demonstrate this behavior, take a look at the following code sample.

`

<style type="text/css">
div        { width : 100px; height: 100px; border: thin solid red;}

blockquote { width: 125px; height: 100px; margin-top: 50px; margin-left: 50px; border: thin dashed black} cite { display: block; text-align: right; border: none} p { margin: 0;} </style>

<div> <blockquote> <p>some text long enough to make it interesting.</p> <cite>- anonymous</cite> </blockquote> </div>

`

The following image shows how this code sample is rendered in IE6.

The Box Model in IE6

In contrast, the next figure shows how IE7 renders the same code.

The Box Model in IE7

As you can see, we now honor the height and width settings of a box. In this example, the <blockquote> content now renders outside of the boundaries of the parent <div> (box with red borders).

If your layout relied on us "growing" the box (if your content did not fit the dimensions you gave it) then this can lead to breaks. You can easily discover breaks related to overflow by observing content suddenly overlapping other content.

CSS Filters

Even though standards like CSS are available it is not a guarantee that all browsers render the same way. The standard might have undefined parts, not all components are equally implemented by all browser vendors, and existing implementations might have bugs. The CSS standard does not provide a way to target specific browser versions and as a result the Web developer community has developed CSS filters (also called "CSS hacks"). These filters take advantage of browser bugs or unimplemented features to hide CSS style rules from specific browsers. As we fix these bugs and improve CSS support, some CSS filters will stop working.

If you use such filters, you should understand their effects. In this long run, this will help you create designs that more effectively adapt to improved CSS support in later versions of Internet Explorer and other browsers. 

In IE7, we fixed many underlying parser bugs that prevented the following filters from working in earlier versions of IE. If your page contains these filters, please remove or replace them (at the end of this article we will offer other means of targeting reliable IE versions).

* HTML Filter

This CSS filter is based on a parser bug. It used to show rules exclusive to Internet Explorer. These constructs will now be ignored by Internet Explorer 7 and later.

`

/* The following rules used to apply only to
IE but now get ignored by IE7 and higher */

  • html{ }

  • html body{ }

  • html .foo{ }

`

_ Underscore Filter

This CSS filter is based on a parser bug. It used to show properties exclusive to Internet Explorer. These constructs will now be treated as a "custom property" by Internet Explorer 7 and later. Custom property means that it is still in the OM and can be queried through script but does not natively apply its value.

`

/* The following rule used to apply min-height
to browser who understand this property and
height to IE.  In IE7, _height will be treated
as a custom property (no height will be applied) */

.myclass { min-height: 300px; _height: 300px; ... }

`

/**/ comment filter

This CSS filter is based on a parser bug. It used to hide properties exclusive to Internet Explorer under the strict doctype (this filter did not work under quirks mode). In Internet Explorer 7, the property will now be parsed and applied.

`

/* The following rule used to hide the height
property to Internet Explorer. In IE7, the
value will be applied */

.myclass { height/**/: 300px; ... }

`

"html > body" child selector filter

This CSS filter is based on a previously unimplemented feature in Internet Explorer. It used to hide declarations exclusive to Internet Explorer. Starting with version 7, Internet Explorer will apply the properties within the declaration.

Note: CSS style rules that rely on child selectors are only considered CSS filters when used to detect specific browsers or browser versions. 

`

/* The following rule used to hide the height
property to Internet Explorer. In IE7, the
value will be applied */

html > body { height: 300px; ... }

`

"head + body" adjacent selector filter

This CSS filter is based on a previous non-implemented feature in Internet Explorer. It used to hide declarations exclusive to Internet Explorer. Now Internet Explorer will apply the properties within the declaration.

Note: CSS style rules that rely on adjacent selectors are only considered CSS filter when used to detect specific browsers or versions.

`

/* The following rule used to hide the height
property from Internet Explorer. In IE7,
the value will be applied */

Head + body { height: 300px; ... }

`

"head:first-child + body" first child and adjacent selector filter

This CSS filter is based on two previous non-implemented features in Internet Explorer (:first-child pseudo class and the adjacent selector). It used to hide declarations exclusive to Internet Explorer. Now Internet Explorer will apply the properties within the declaration.

Note: CSS style rules that combine :first-child selectors with adjacent selectors are only considered CSS filters when used to detect specific browsers or browser versions.

`

/* The following rule used to hide the height
property from Internet Explorer. In IE7,
the value will be applied */

head:first-child + body { height: 300px; ... }

`

My Page is Broken, What Can I Do?

This section presents possible strategies for working around problems.

Working around overflow:visible default behavior

If no width or height is set, then boxes in your layout should pretty much behave like they did with IE6 (exceptions if you have very long words or pre content that might overflow the viewport). You should be fine here.

There are two cases where your layout might break due to the new behavior:

If you have set a width or height on your content and you did not realize that your content is actually larger than the set dimensions.

This case is very easy to solve. Just identify the correct size of your content (the ruler of the Developer Toolbar can help you do it) and set the correct dimensions on your box.

If you have dynamic content that requires changes to your box size on the fly. This can happen if you insert content dynamically, or you did not specify a font size and the user changes it as part of the user settings.

There is a declarative solution using min/max width/height properties that can correct behavior issues introduced by the overflow correction. Consider the following example.

`

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">

<html> <title> CSS: Overflow:visible and Min/Max </title> <style>

.DivClass1 { background:orange; width:150px; height:100px; } </style> <body>

    &lt;div contenteditable=true class=DivClass1&gt;
        this is a DIV with a fixed width and height
        of 100 pixels, in IE 6, the height of the DIV will extend to the
        height of the content. In IE7, the height of the DIV is 100px as
        specified, but the text overflows outside of the box.
    &lt;/div&gt;
  
&lt;/body&gt;

</html>

`

You can correct this behavior by using the new min-height property for all modern browsers like IE7. To ensure that your behavior does not change for older versions of IE, we recommend the use of conditional comments.

`

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">

<html> <title> CSS: Overflow:visible and Min/Max </title>

<!-- Will only be read by IE versions less then IE 7--> <!--[if lt IE 7]> <link rel="stylesheet" type="text/css" href="Demo/iestyles.css" /> <![endif]-->

<style> .DivClass1 { background:orange; width:150px; min-height:100px; // will be ignored by IE6 } </style>

&lt;body&gt;

    &lt;div contenteditable=true class=DivClass1&gt;
        this is a DIV with a fixed width and height
        of 100 pixels, in IE 6, the height of the DIV will extend to the
        height of the content. In IE7, the height of the DIV is 100px as
        specified, but the text overflows outside of the box.
    &lt;/div&gt;
  
&lt;/body&gt;

</html>

`

In iestyles.css, you would specify the behavior of IE6 and below.

<pre IsFakePre="true" xmlns="https://www.w3.org/1999/xhtml">.DivClass1 { height:100px; // applies only to versions that do not understand min-height }</pre>

The use of conditional comments is an easy and maintainable way to separate behavior of older IE versions form the more standards compliant behavior of IE7.

Broken pages due to CSS filter enchancements

If your page designs break in IE7 strict mode, you have three options:

  1. First, try to create standards-based, cross-browser designs. By simplifying your page, you might remove the problem and reduce your maintenance cost.

  2. Use conditional comments to work around issues that only affect Internet Explorer.

  3. If you have to use CSS filters, consider only filters that target older browser versions. This will minimize your risk of future problems.

Using Conditional Comments

Conditional comments have been available since Microsoft Internet Explorer 5, and provide easy and maintainable ways to detect IE's browser type and version. Since the syntax is based on comments, other browsers will just ignore the statements. This is a great way to replace filters like the * HTML filter that specifically tries to target IE. To keep it clean we propose that you use conditional comments to set up a link to an IE-specific style sheet.

<pre IsFakePre="true" xmlns="https://www.w3.org/1999/xhtml"> &lt;!--[if IE]&gt; &lt;link rel="stylesheet" type="text/css" href="iestyles.css" /&gt; &lt;![endif]--&gt; </pre>

Effectively Using CSS filters

We recognize the pain caused by working around differences in browser behavior. CSS filters are not inherently bad if they are used with two guidelines in mind:

  1. Target ONLY "older than current" (frozen or abandoned) versions of browsers. This will ensure that your filter will not break with new browser releases. There are filters for example that only target IE5.5 and earlier. They are relatively safe to use.

  2. Be aware that they are filters. Make sure you can maintain them in case they do break (for example if a security patch is issued for a down level version etc.). Provide comments that clearly mark them as filters.

We are listening and balancing the need for compatibility

We heard the feedback from the developer community that has asked us for a long time to move to a more standard-compliant rendering behavior. We are balancing this request with the needs of our customers to not have their pages broken. To find a balance we introduced a strict mode in IE6 that lets authors opt in to the more standards-compliant rendering. Pages authored under non-strict mode (quirks) will not change behavior in IE7 and will not be affected by broken CSS filters. Under strict mode, we have made and will continue to make changes to be more standard-compliant. As a side product, content from an older strict version might break when we have to do behavior changes to be more complaint. This has happened to the broken CSS filters. They relied on specific implementation behavior rather than the CSS specifications.

We hope this article provided some help in understanding the root cause of CSS compatibility issues with IE7 and offered enough ideas to help you mitigate the problem.

Markus Mielke and Dave Massy are program managers on the Internet Explorer team.