Wake up and smell the IE7!

Visited 810 times | Submited on 2007-07-06 10:31:45

Before we get into the issues that plagued the sites in our study, let’s quickly take a look at one that didn’t. “Why bother?” you might say. Well, if your site’s breaking in IE7, then this is the first problem you should attempt to rule out.

Put simply, if you’re using JavaScript or server-side logic to serve different styles to different browsers, you need to make sure that you’re not inadvertently excluding IE7.

How might you be excluding IE7? Well, perhaps you’ve written a script that applies one set of styles when your pages are viewed in IE6 and another set of styles when they’re viewed in all preceding versions of IE. This would have worked nicely in the past, but now that IE7 has arrived it will cause you problems. Why? Because while you’ve specified what would happen in IE6 and earlier, you’ve forgotten to specify what would happen in later versions of IE - later versions like IE7.

If you find that this is the cause of your IE7 problems, the short-term solution is simply to extend your script to target IE7 with a new set of styles. In the long term however, you might want to take a look at an alternative solution.

Browser detection is notoriously problematic: using JavaScript to sniff the browser will only work when JavaScript is enabled in users’ browsers, while parsing the User-Agent String (via JavaScript or server-side code) can prove to be even more unreliable due to “User agent spoofing“. In short, browser detection is not a very robust solution.

The only reliable method of detecting IE going forwards involves the use of conditional comments. This is the only method that Microsoft guarantees that it will support over the long-term. Conditional comments have been available since IE5 and, despite being proprietary, are valid forms of HTML/XHTML markup - other browsers simply ignore them since the syntax of these statements is based on regular HTML comments.

The disadvantage of using conditional comments is that they clutter up your HTML files and require you to keep multiple stylesheets (rather than a single centralised resource). Wouldn’t it have been better to have made conditional comments part of CSS and not HTML, Microsoft?

Examples


<!--[if gt IE 6]>
<link rel="stylesheet" type="text/css" href="ie7andlater.css"/>
<![endif]-->

<!--[if lte IE 6]>
<link rel="stylesheet" type="text/css" href="ie6andearlier.css"/>
<![endif]-->

<![if !IE]>
<link rel="stylesheet" type="text/css" href="otherbrowsers.css"/>
<![endif]>

MSDN has more information about conditional comments here.

I have nothing to declare except my XML-ness

Having sorted out any IE-detection-related issues, the next thing to check is the first line of markup on your problem pages. The first line on both the Alliance and Leicester and Lastminute.com homepage - two of the most badly broken homepages found during our study - read as follows:

 <?xml version="1.0" encoding="iso-8859-1"?>

For the uninitiated, this statement is an XML declaration (not to be confused with an “XML prolog” which is the combined total of an XML declaration and a DOCTYPE declaration); its purpose being to tell the browser which version of XML your XHTML pages complies with and (optionally) to specify the type of character encoding you’re using.

The W3C says the following about XML declarations:

“An XML declaration is not required in all XML documents; however XHTML document authors are strongly encouraged to use XML declarations in all their documents…”

So you don’t have to use them, but they’d like you to. And as a result of this “strong encouragement”, many well-meaning would-be standardistas have added them to their pages with the commendable aim of achieving the highest possible levels of compliance.

Unfortunately, several older browsers can’t handle XML declarations. In fact, they have a nasty effect on them. As Jeffrey Zeldman puts it in Designing With Web Standards, “after imbibing the XML element, they stagger and stumble and soil themselves, bringing shame to their families and eventually losing their place in society”. Some crash as a result, others display nothing. IE6 does something a little more subtle: it ignores your DOCTYPE.

As you know, browsers use the DOCTYPE to toggle between rigorous standards-compliance mode (called strict mode in IE) and fault-tolerant, backwards-compatible quirks mode (so called because it mimics the quirks of various old incompliant browsers that most old websites were designed for). In most modern browsers, a valid XHTML DOCTYPE (complete with full URI) results in pages being rendered in standards-compliant mode, treating your XHTML and CSS content in accordance with the relevant W3C specifications. And IE6 is no exception. Unless you stick an XML declaration in front of it.

In IE6 the DOCTYPE must be the first line in your XHTML file. If it isn’t, your request for standards/strict mode will be ignored and quirks mode will be used instead (Opera 7 does the same). This means that you get IE’s original (read: erroneous) interpretation of the box model and a number of other “features” that don’t align with the W3C specs.

In IE7 however, this bug has been fixed. IE7 therefore doesn’t care whether your DOCTYPE declaration is preceded by an XML declaration or not - either way, it gives you strict mode… and therein lies a problem. If your page starts with an XML declaration you’ll get quirks mode in IE6 and strict mode in IE7. You can verify this yourself by typing the following line of JavaScript into the URL bar of both browsers after your web page has loaded.

 javascript:alert(document.compatMode);

In IE6, you’ll see a dialog box displaying the word “BackCompat”, meaning that it is in quirks mode. While, in IE7, you’ll see “CSS1Compat”, meaning that it’s in standards-compliant strict mode. This discrepancy explains the inconsistencies you’re seeing in the two browsers’ displaying of your pages.

How do you fix these inconsistencies? I’d recommend removing your XML declarations, so that your pages render in strict mode in both IE7 and IE6 - and then reworking your styles, so that your pages look identical in both browsers.

“Remove my XML declarations? Is that legit?” Yes. Firstly, they’re optional - see the quote from the W3C above - so omitting them isn’t a crime. Secondly, unless you’re part of a very small minority of developers, you probably aren’t serving your pages as XML anyway. Check the head of your document - do you see markup like this?

 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> 	

If you do, guess what, you’re serving HTML, not XHTML (actually, you’re serving HTML compatible XHTML1.0, but let’s not get picky), regardless of what your DOCTYPE says.

You’re only serving true XHTML if you see application/xhtml+xml in place of text/html in your version of the above. And this isn’t recommended for most purposes (at least, it isn’t recommended for now) as application/xhtml+xml isn’t supported by the majority of browsers. (IE, for example, will ask you if you want to save these types of documents, rather than displaying them as web pages).

Furthermore, newer browsers may opt to validate your markup if you include an XML declaration and specify a Content-Type of application/xhtml+xml. This could be disastrous if parts of your pages are inserted dynamically from a content management system. As you won’t have control over the content in the CMS, you won’t know whether it’s 100 per cent XML-valid or not. And if it’s not 100 per cent XML-valid, the newer browsers will likely choose not to display it. (Let’s face it, in the real world you can bet your life it won’t be XML-valid - the combination of CMS and business user doesn’t often produce solid markup!).

If you’re serving your XHTML as text/html however, you can at least rely on browsers displaying your content as you intend (although if you’re going to stick with dishing up text/html, you may be better off slashing the X off XHTML and switching back to plain ol’ HTML - but that’s a discussion for another day).

“But wait!” I hear you say, “I can’t get rid of my XML declarations because I need to specify a character encoding!” Don’t panic. You can still get rid of the XML declarations, just update the Content-Type element in the head of your documents instead. For example, if you want to specify an UTF-8 encoding to keep your international user-base happy, simply insert:

 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 	

Thinking outside of the (old) box model

If you’ve addressed the previous issues, and you’re sure that your pages are being displayed in strict mode in both IE6 and IE7, your problems might stem from IE7’s updated handling of the CSS box model.

The update is best explained by example. Imagine that you’ve created a box with a width and height of 100px. Now imagine that the content you’ve placed within it is wider and taller than 100px. What should happen? Well, in IE6, the box will automatically stretch to fit around the content (or at least it will as long as the box keeps its default overflow value of visible). This sounds like a good idea, because it looks messy when content bleeds across a box’s borders. However, this isn’t the behaviour prescribed by the W3C’s CSS2.1 specification (and with good reason).

The CSS2.1 spec says that the width and height that you specified for the box should be honoured at all costs if the box’s overflow property is set to visible (its default setting). If the content within the box is wider and/or taller - causing “overspill” - well shucks, you should have created a bigger box then, shouldn’t you?

Why does the spec recommend such behaviour? Well, automatically expanding boxes have a knock-on effect on the other elements placed around them. So if your 100px-wide box suddenly becomes bigger it will displace the elements around it. The result: a fractured page layout.

In ensuring that heights and widths are honoured where specified, developers are given complete control over their page layouts. If you want a box that’s 100px wide, state that in your stylesheet and you’ve got it. If you want one that expands and contracts in accordance with the size of its contents, leave its width set to auto and overflow set to visible and it’s yours. For even more flexibility, you can use min and max settings.

The release of IE7 sees IE’s box model updated to adhere to the CSS2.1 specification - thereby creating inconsistency between IE6 and IE7 in strict mode. So, if you’re finding that your content is bursting out from its containing box, this could be the problem. (It certainly played a part in breaking BHP Billiton and Teletext Holidays‘ homepages in IE7).

Filtering out the filters

A number of the hacks and filters used to target IE no longer work in IE7. These workarounds took advantage of various bugs and unimplemented parts of the CSS2.1 specification to either hide styles from IE while having other browsers apply them; or to apply styles in IE while hiding them from other browsers. Here are the ones that are affected:

The star html filter (aka The Tan hack)

The star html filter is used to apply CSS rules in IE, while hiding them from other browsers. It is most commonly used to address the aforementioned box model problems in IE5, IE5.5 and IE6 (Mac and Windows versions).

During our study, we found that sites like Woolworths, UpMyStreet.com and Lastminute.com were using this filter (as part of the Holly hack) to address the Peekaboo bug in IE6. British Energyand O2 also used it to address layout inconsistencies.

The filter works by exploiting a bug in the way that the older versions of IE interpret the “star” - or “universal selector” as it’s officially known. The CSS2.1 spec says that the universal selector should match all descendant elements in the document tree (think of it as a wildcard). Combining the star with html to make * html is the equivalent of saying p html, body html or div html (or indeed [any other html element] html). This is clearly illegal as html is always the root element in a document and as such can never be the child of any other element.

Most browsers recognise * html as illegal syntax and ignore it (along with its accompanying declaration block to boot). IE5, IE5.5 and IE6 however, ignore the star but parse all that follows, therefore considering * html the equivalent of html.

This bug has now been fixed, meaning that IE7 will ignore star html filtering in accordance with the CSS2.1 specification.

Examples

The following declarations are parsed in older versions of IE, but ignored in IE7.

* html {
 ...
}

* html body {
 ...
}

* * body {
/*This is also ignored in IE7 because the body element can never be a grandchild of the root element*/
... 

An example from British Energy

 * html #main { height: 98% } 

The underscore filter

Like the star html filter, the underscore filter is also used to apply rules in IE while hiding them from other browsers. Unlike the star html filter, however, it only works in Windows versions of IE (not Mac) making it a little less flexible.

During our study, we found that Lastminute.com made use of this filter to address layout issues, as did Opodo.

The filter works by exploiting a bug in the way that older versions of IE interpret the underscore character. The CSS2.1 specification reserves underscores (and dashes) for vendor-specific extensions (aka “custom properties”). Thus, rules like _myprop: foo should be ignored by browsers, unless they implement their own proprietary _myprop property.

Most modern browsers follow this guideline. Older versions of IE, however, ignore the underscore but read the text that follows. Thus, they treat statements like _myprop: foo as the equivalent of myprop: foo (no underscore) and try to apply it as a style. As a result, developers could prefix any standard CSS rule - for example, width: 300px - with an underscore to make older versions of IE apply it, while keeping it hidden from all other browsers.

This bug has now been fixed, meaning that IE7 treats properties prefixed with an underscore as vendor-specific extensions per the CSS2.1 standard. As a result, the browser no longer attempts to apply statements like _width: 300px as CSS rules. (However, they still appear in the object model and can be queried via scripts.)

Examples

_height will override the preceding height rule in older versions of IE, but will be ignored in IE7

#promo {
min-height: 300px;
height: auto;
_height: 300px;
...

An example from lastminute.com

#homepage_search_category ul li.first {
_top: -2px !important; /*underscore hack fix for IE/Win :( */
}

The comment after property filter

Unlike the star html and underscore filters, this filter is used to hide rules from IE while having other browsers apply them. It only works in strict mode however (not quirks mode).

During our study, we found that Lastminute.com made extensive use of this filter to correct font size and layout issues. Opodo also used this filter to display form elements correctly in IE6.

The filter works by exploiting a bug in the way that older versions of IE interpret CSS comments. When these browsers encounter a comment - i.e. /**/ - placed after a rule’s property name, they choke and skip the value that appears thereafter, proceeding directly to the next line of code.

This bug has now been fixed, so in IE7 these rules are parsed in full and applied.

Examples

The following height rule is ignored by older versions of IE, but applied in IE7

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

An example from lastminute.com

td, th {
font-size:80% !important;
font-size/**/:100% !important;
font-size/**/:80%
}

td, th {
font-size:80% !important;
font-size/**/:100% !important;
...
}

The child selector filter

The child selector filter is used to hide rules from IE while having other browsers apply them. During our study, we found that O2 and BP made extensive use of this filter to deal with box model inconsistencies.

Child selectors - e.g. html > body - are used to apply styles to elements that are direct children of other elements. However, despite being part of the CSS2.1 specification, they aren’t supported in older versions of IE and are therefore ignored.

Support for child selectors has been added in IE7, so these rules are now parsed and applied per the standard.

Examples

The following height rule is ignored by older versions of IE, but applied in IE7

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

An example from BP

html > body .effLoginContainer{
padding: 5px 10px 7px 10px;
background-color: #E7F7E7;
}

The adjacent selector filter

Like the child selector filter, the adjacent selector filter is used to hide rules from IE while having other browsers apply them. During our study, we found that Lastminute.com made use of this filter to align table data.

Adjacent selectors are similar to child selectors. However, while child selectors are used to match the children of an element, adjacent selectors are used to match siblings. Thus, the adjacent selector tr + tr matches any table row that follows another table row and results in styles being applied to every row in a table other than the first. However, despite being part of the CSS2.1 specification, they aren’t supported in older versions of IE and are therefore ignored.

Support for adjacent selectors has been added in IE7, so these rules are now parsed and applied per the standard.

Examples

The following height rule is ignored by older versions of IE, but applied in IE7

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

An example from lastminute.com - used to align text to the right in all table cells in a row except for the first.

 table.priceDestination tbody td + td { 	text-align: right 	} 

The first child and adjacent selector filter (aka The Owen hack)

This hack takes the aforementioned adjacent selector filter and gives it a twist, by adding in the :first-child pseudo-class. Like the adjacent selector filter it is used to hide rules from IE while having other browsers apply them.

It usually appears in the form of head:first-child + body, which means “select the body element if the body and head elements are siblings AND the head element is the first child of its parent element.”

Since the body and head elements are always siblings, the first part of this statement is true. And since the head element is always the first child of html (its parent element) the second part of the statement is also true.

Despite being part of the CSS2.1 specification, older versions of IE don’t support the first-child pseudo-class or adjacent selectors and ignore them wherever they are found.

Support for both the first-child pseudo-class and adjacent selectors has been added in IE7 however, so these rules are now parsed and applied per the standard.

Examples

The following rule used to hide the height property from Internet Explorer. In IE7 this declaration will be applied.

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

Note: we found no examples of the first child and adjacent selector filter during our study.

The solution?

Purists will recommend that you remove the need to use these types of filters by restricting your designs to only the CSS features that work consistently across all browsers.

This is fine in theory. However, in practice, clients’ demands often mean that we need to use CSS features that don’t work consistently across all browsers and then fudge them to make them appear as though they do. So when filters like the above stop working, we need to find something to replace them with.

The only reliable replacement for filters that target versions of IE are - yes, you’ve guessed it - Microsoft’s proprietary conditional comments. We’ve discussed them before so I won’t blather on about them again; save to say that here’s how they can be used to supply IE7 with one set of styles, while supplying older versions of IE with another - thereby performing the same function as outdated hacks that don’t work any more.

<!--[if gt IE 6]>
<link rel="stylesheet" type="text/css" href="ie7andlater.css"/>
<![endif]-->
<!--[if lte IE 6]>
<link rel="stylesheet" type="text/css" href="ie6andearlier.css"/>
<![endif]-->

Final thoughts

The results of our study suggest that around 12.7 million websites are in need of a little TLC because of IE7. Maybe even more. However, this article has hopefully shown that the most common problems are easy to diagnose and not too difficult to fix. As always, we welcome your thoughts on the subject.

Author: Simon Griffin
Source: thinkvitamin.com



Add your comment

Name:(required)
E-mail address:(optional)
Comment:(required)
Repeat the number for validation: (required)

Browse by Tags:


Related Articles:

Text Link Ads

Statistics

Total 296 articles submitted
Latest submission at January 28, 2008 15:13

Feedback

Use this email below to send us your suggestions and feedback. We value your opinion.
info (at) theitarticles.com