一个正在奋斗中的IT民工

研究+交流+分享=提高

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::
Internet Explorer conditional comments
Conditional comments are a proprietary, and thus nonstandard, Microsoft extension of
regular (X)HTML comments. As the name suggests, conditional comments allow you to
show blocks of code depending on a condition, such as a browser version. Despite being
nonstandard, conditional comments appear to all other browsers as regular comments,
and so are essentially harmless. Conditional comments first appeared in IE 5 on Windows
and are supported by all subsequent versions of the Windows browser.
To deliver a specific stylesheet to all versions of IE 5 and above, you could place the following
code in the head of your (X)HTML document:
<!-- [if IE]
<style type="text/css">
@import ("ie.css");
</style>
-->
Versions of IE 5 and above on Windows would receive the stylesheet ie.css while all other
browsers would simply see some commented-out text. With conditional comments you
could target a particular browser such as IE 5.0:
<!-- [if IE 5]
<style type="text/css">
@import ("ie50.css");
</style>
-->
You could also target sets of browsers such as IE 5.5 and greater:
<!-- [if gte IE 5.5000]
<style type="text/css">
@import ("ie55up.css");
</style>
-->
Or IE 5 and IE 5.5:
<!-- [if lt IE 6]
<style type="text/css">
@import ("ie.css");
</style>
-->
This technique works extremely well and is relatively simple to remember. The main downside
is that these comments need to live in your HTML, not your CSS. If at some stage you
wish to stop supporting a particular browser, you will need to remove the comments from
every page. If this is a concern, you may want to look at Tantek Çelik’s selection of filters,
which we’ll look at next.

 

Band pass filters

Tantek Çelik created a series of filters (http://tantek.com/CSS/Examples/) based on

browser parsing errors that allow you to supply stylesheets to selected browsers using the

@import rule. Because this is a CSS rule, all of these filters can live in a single CSS file,

allowing all your filtered files to be controlled from one place. Separating your hacks into

browser-specific CSS files can greatly simplify your hack management. If you decide to

remove support for a specific browser, such as IE 5.0, you can simply remove the associated

stylesheet, rather than having to trawl through lines of code.

To pass a CSS file to IE 5 and 5.5 on Windows, you can use Tantek’s mid-pass filter:

@media tty {

i{content:"\";/*" "*/}} @import 'ie5x.css'; /*";}

}/* */

This filter looks like a jumble of meaningless rules, and to many browsers that is exactly

what it is. Browsers only capable of understanding CSS 1 will not recognize the @media rule

and completely ignore it. More capable browsers will see a single declaration inside the

@media rule, targeting the <i> element. Due to the existence of an escape character present

before the second quote mark, the value of the content property is treated as a single

string of meaningless characters. Essentially, modern browsers will see a rule that looks like

this:

@media tty {

i {

content:"Blah, blah blah";

}

}

The tty media type refers to terminals and teletype machines. Fortunately, no devices currently

support this media type, so the whole rule is effectively ignored by compliant

browsers.

However, IE 5.x/Win doesn’t honor the escape character, and closes the content declaration

prematurely. The following characters close both the <i> and @media rules, causing

the @import rule to be applied. Any superfluous characters are commented out, and the

whole rule looks like this to IE 5.x/Win:

@media tty {

i{

An escape character is a reserved character—usually a backslash—that causes

the following reserved character to be ignored by the parser. So if you wanted to

auto-generate a quote mark using the CSS content property, you would have to

escape it, or it would prematurely close the open quote:

blockquote:before {content: "\""}

CSS MASTERY: ADVANCED WEB STANDARDS SOLUTIONS

158

content:"blah";

/* blah */

}

}

@import 'ie5x.css';

/* blah */

This is all quite complicated, so luckily you don’t need to know how these filters work; you

just need to know how to use them.

In order to target a particular version of IE 5.x/Win, two variations of the mid-pass filter

were created that exploited various bugs in those particular browsers. These were called

the IE 5/Windows band pass filter:

@media tty {

i{content:"\";/*" "*/}}; @import 'ie50win.css'; {;}/*";}

}/* */

and the IE 5.5/Windows band pass filter:

@media tty {

i{content:"\";/*" "*/}}@m; @import 'ie55win.css'; /*";}

}/* */

The other browser you may want to explicitly target is IE 5.2 on the Mac. You can do this

using Tantek’s IE 5/Mac band pass filter, which exploits a different escaping bug, this time

within comments:

/*\*//*/

@import "ie5mac.css";

/**/

IE 5/Mac incorrectly escapes the second asterisk, causing the @import rule to be applied.

As such, IE 5/Mac sees something like this:

/* blah */

@import "ie5mac.css";

/**/

All other browsers correctly ignore the escaping element, as it is enclosed within a comment,

and the @import rule is commented out. Essentially, all other browsers see a rule

that looks like this:

/* blah *//*

blah

*/

As with the other band pass filters, it is not necessary to understand how this filter works

in order to use it. The beauty of these filters is they specifically target bugs in older, outof-

date browsers. Therefore, you should be able to use these filters safe in the knowledge

that they shouldn’t cause problems in newer browsers. 

 

Filtering individual rules and declarations

If your CSS files are small and you only need to employ a few hacks, you can choose to add

the associated filters into your main stylesheets. However, remember that all these rules

and declaration-specific filters do add extra weight and complexity to your code. 

The child selector hack

The safest filters rely on unimplemented CSS rather than browser bugs. As these filters use

valid CSS selectors to apply valid declarations, they are not, strictly speaking, filters at all.

They are simply valid CSS rules that certain browsers fail to understand. The first of these

filters is known as the child selector hack. IE 6 and below on Windows does not support

the child selector, so you can use it to hide rules from those browsers. For this filter to

work, you must make sure that there is no whitespace before or after the child selector.

In this example, the child selector hack is being used to hide a transparent background

PNG image from IE 5-6/Win:

html>body {

background-image: url(bg.png);

}

IE 7 is expected to support the child selector. It is also expected to support native PNG

transparency. By using the child selector filter in this way, you are building in forward compatibility

by allowing newer versions of IE to view the transparent background without

needing to revisit the code. 

Attribute selector hack

Another interesting way to filter rules is by using the attribute selector. Many modern

browsers such as Safari and Firefox support the attribute selector, but it is not supported

by IE 6 and below. As such, you can use the attribute selector as a way of styling classes

and IDs for more advanced browsers. In this example, the attribute selector is being used

to apply a background PNG to the content div on more compliant browsers:

div[id="content"] {

background-image: url(bg.png);

}

Again, both the attribute selector and PNG alpha transparency support are scheduled for

IE 7, which means this method should work seamlessly when IE 7 launches.

This method can be used in some very creative ways. For instance, Andy Clarke used

this technique to create two completely different themes for his personal site,

www.allthatmalarkey.co.uk. More advanced browsers get a nice, high-definition

color theme (see Figure 8-2), while less capable browsers get a retro two-tone theme (see

Figure 8-3). 

The star HTML hack

One of the best-known and possibly most useful CSS filters is known as the star HTML

hack. This filter is incredibly easy to remember and targets IE 6 and below. As you are

aware, the HTML element is supposed to be the first, or root, element on a web page.

However, all current versions of IE have an anonymous root element wrapping around the

HTML element. By using the universal selector, you can target an HTML element enclosed

inside another element. Because this only happens in IE 6 and below, you can apply specific

rules to these browsers:

* html {

font-size: small;

}

Adding a universal selector followed by an html type selector to the start of any regular

CSS rule will hide that rule from everything other than IE. The most common way to use

this filter is to set a rule that you want all browsers other than IE to apply, and then override

that rule in IE using the star HTML hack. For example, IE renders 1-pixel dotted lines

as ugly dashed lines by mistake. To avoid these ugly dashed lines, you could set the hover

border style on your anchors to dotted but override this in IE, making them solid instead:

a:hover {

border: 1px dotted black;

}

* html a:hover {

border-style: solid;

}

It is very unlikely that this bug will appear other browsers, and it is expected to be fixed

in IE 7. Therefore, the star HTML hack provides a relatively safe way of targeting IE 6

and below. 

IE/Mac commented backslash hack

Another useful filter is known as the commented backslash hack. IE 5 on the Mac incorrectly

allows escaping inside comments, so this filter works by adding a backslash in front

of the closing comment identifier. All other browsers will ignore this escape and apply the

following rules. However, IE 5/Mac will think that the comment is still open, ignoring

everything until the next close comment string.

/* Hiding from IE5/Mac \*/

#nav a {

width: 5em;

}

/* End Hack */

This bug forms the basis of the IE 5/Mac band pass filter you saw earlier.

CSS MASTERY: ADVANCED WEB STANDARDS SOLUTIONS

162

If you combine the star HTML and commented backslash filters, you get the Holly hack,

named after its inventor, Holly Bergevin. By combining these two rules, it is possible to

apply rules to IE 6 and below on Windows:

/* Hiding from IE5/Mac \*/

* html {

height: 1px;

}

/* End Hack */

This can be very useful for attacking and fixing all kinds of Windows-specific IE bugs, and

is possibly one of the most used filters around. 

“Big John” and Holly Bergevin run www.positioniseverything.net, the definitive

resource on browser bugs and workarounds. Together they discovered or

documented many of the hacks and bugs seen in this and the following chapter.

The escaped property hack

IE 5.x on Windows ignores escape characters. This bug forms the basis of the mid-pass filter

you learned about earlier. It also forms the basis of the much easier escaped property

filter. As the name suggests, this filter works by adding an escape character within a property.

All modern browsers should ignore this escape character, but IE 5.x/Win thinks this is

part of the property name and, not recognizing the property, ignores the declaration.

#content {

w\idth: 100px

}

As such, the escaped property filter provides a simple way of hiding styles from IE 5.x/Win.

However, you need to be careful when using this filter as the backslash character cannot

come before the numbers 0 to 9 or the letters a to f (or A to F). This is because these values

are used in hex notation and may therefore get escaped. 

Tantek’s box model hack

Tantek’s box model hack was one of the first CSS filters ever invented. Tantek Çelik created

this filter at the behest of Jeffrey Zeldman to allow him to work around IE’s proprietary

box model (see Chapter 9). This filter works by passing one width to IE 5 on Windows and

another width to all other browsers. It does this using the same escape character bug used

in the band pass filters:

div.content {

width:400px;

voice-family: "\"}\"";

voice-family:inherit;

width:300px;

}

“Big John” and Holly Bergevin run www.positioniseverything.net, the definitive

resource on browser bugs and workarounds. Together they discovered or

documented many of the hacks and bugs seen in this and the following chapter.

Unfortunately, Opera 5 has the same parsing bug as IE 5.x/Win. As such, a second rule is

required to give Opera the correct width:

html>body .content {

width:300px;

}

If it weren’t for this filter, pure CSS layout may never have been possible. However, these

days it is seen as an ugly and complicated filter, best avoided. I have included it in here

purely for its historical significance and because you will still see it being used in older

stylesheets. These days, it is much more common to use the modified simplified box

model hack. 

For more on the history of this, and several other filters, see Tantek Çelik’s excellent

article, “Pandora's Box (Model) of CSS Hacks and Other Good Intentions,”

at http://tantek.com/log/2005/11.html.

The modified simplified box model hack

The escaped property hack can be combined with the star HTML hack to create the modified

simplified box model hack, or MSBMH for short. This hack is used for working around

IE’s proprietary box model by providing one length value to IE 5.x/Win and then the correct

length value to IE 6/Win and all other browsers:

* html #content {

width: 80px;

w\idth: 100px;

}

html #content {

width: 100px;

padding: 10px;

}

The modified simplified box model hack is easier to remember and much cleaner than

Tantek’s box model hack, and so is currently the preferred box model hack. This filter can

be used for more than just box model hacks, so don’t let the name limit you. 

The !important and underscore hacks

There may be some instances where you wish to apply one declaration to IE 6 and below on

Windows and another to all other browsers, within the same rule. To do this, you could use

the commented property hack, or you could use the !important or the underscore hack.

For more on the history of this, and several other filters, see Tantek Çelik’s excellent

article, “Pandora's Box (Model) of CSS Hacks and Other Good Intentions,”

at http://tantek.com/log/2005/11.html.

The !important hack works because IE 6 and below on Windows has problems dealing

with multiple properties in a single rule:

#nav {

position: fixed !important;

position: static;

}

IE 4-6/Win will ignore the first declaration and apply the second. All other browsers will

apply the first declaration because it is using the !important keyword, which increases the

rule’s priority within the cascade (see Chapter 1).

Similar to the !important hack is the underscore hack. By placing an underscore in front

of a property, compliant browsers will no longer recognize that property and the declaration

will be ignored. However, IE 6 and below on Windows ignores the underscore and

thus applies the rule. So in this example, all modern browsers will apply a position of

fixed, skipping the unknown second rule. IE 4-6/Win will ignore the underscore and will

override the first rule, setting the position to static.

#nav {

position: fixed;

_position: static;

The Owen hack

All of the filters so far have been aimed at various versions of IE. This is partly because IE

has more bugs than most current browsers. However, it is also because IE is by far the most

prevalent browser, so more bugs get found and documented. But there are other buggy

browsers out there, including Opera 6 and below.

The Owen hack allows authors to hide styles from Opera 6 and below, as well as from IE 6

and below on Windows. This filter works because these browsers do not implement the

first-child selector. Because there can only ever be one head element, it is always a firstchild.

The body tag always comes after the head tag, and so can be targeted using an adjacent

sibling selector. The resulting selector is understood by more compliant browsers,

while being ignored by version 6 and below of Opera and IE on Windows.

In the following example, the Owen hack is being used to add a background PNG image on

the body tag for more compliant browsers, hiding it from IE/Win and Opera, versions 6

and below:

head:first-child+body {

background-image: url("bg.png");

}

If you only want to target Opera 6 and below, you need to combine the Owen hack with

the child selector hack. Say you wanted to display an upgrade notice to Opera 6 users. You

would first use the child selector hack to show your upgrade message to every browser

except IE 6 and below on Windows. You could then use the Owen hack to hide the message

from more modern browsers:

html>body #getFirefox {

display: static;

}

head:first-child+body #getFirefox {

display: none;

Summary

In this chapter you have learned that hacks and filters can be an important weapon in any

CSS developer’s arsenal. However, hacks need to be used sparingly, and preferably as a last

resort. If you do need to use hacks or filters, do so with forward compatibility and ease of

maintenance in mind. 

posted on 2009-07-03 16:56  kidi  阅读(325)  评论(0)    收藏  举报