Chapter Seven: Working With, Around, and Against Browsers

Anyone who develops for the web quickly learns that it is a challenge to develop sites that work consistently across browsers. As browsers have matured, and particularly now that Internet Explorer 7 and 8 are starting to replace IE 6, this challenge is receding, but browsers have bugs, and always will. So why do browser bugs cause us so many headaches?

Like operating systems, web browsers provide the underlying technologies that applications (in this case, web pages and web apps) use to present themselves. Of course, unlike desktop applications designed to run on a single operating system, web pages and applications must run on all common browsers. When there’s a bug in an OS, application developers can use workarounds to avoid the consequences of that bug, because the operating system they’re developing for is effectively unique. On the web, however, a workaround for a problem with one browser might cause problems in another browser, or in future versions of the same browser. In essence, we must target multiple operating systems (browsers) with the same code base (our markup, styles, and so on), which is very difficult to do.

Over the last decade, a body of browser hacks has been developed to work around browser bugs and shortcomings—but while some of these methods may “work,” we should nevertheless avoid them, because they are likely to fail in future browsers.

In this chapter, we will focus on some of the most common browser bugs, the reasons why they exist, and sensible, standards-compliant, long-term solutions that work across all browsers.

I hope that future editions of this book will include less and less of this kind of information, as old browsers fade away and new browsers improve their support for standards. The day that Internet Explorer 8 (or even 7) is the baseline version of IE will be a watershed moment in the life of professional developers; when that happens, we’ll be able to turn our backs on many of the challenges addressed in this chapter. Until then, though, we’ll need to find the best way forward that we can.

Three Kinds of Browser Shortcomings

Developers usually need to contend with three different kinds of browser shortcomings:

• Complete lack of support for a feature

• Partial support for a feature

• Buggy support for a feature—that is, support inconsistent with a specification and implementations of the same feature in other browsers

Of these, buggy support is often the most problematic. In the absence of support for a feature in one browser, the progressive enhancement approach suggests that we simply don’t concern ourselves with browsers that lack support (see Chapter 2 if you need to brush up on progressive enhancement). This isn’t always feasible, because some features are fundamental to the way a page works—for example, using CSS3 table display properties to create page layouts will work fine in IE 8 and all other contemporary browsers, but will leave IE 7 and older user agents with broken pages. But on the whole, it’s buggy support, rather than missing support, that causes the most difficulty.

In the pages that follow, we’ll largely focus on Internet Explorer, and particularly on its older versions that are still in use. We’ll do so not because we are anti-Microsoft, but because those browsers—especially IE 6—are the ones that cause the most problems, in large part because some of them are nearly ten years old. The upgrade cycles of other browsers (both on the side of browser makers and browser users) tend to be much shorter than those of IE, so bugs in browsers like Firefox and Safari tend to have a smaller impact on web development.

Browser Modes

Many of the problems developers encounter, particularly with IE, are due to its “backward compatibility mode”—and most of the problems we’ll discuss in this chapter simply go away if we used standards mode to render our pages. So what exactly are these modes?

Quirks Mode and DOCTYPE Switching

Until Internet Explorer 5 for the Mac was released in late 1999, browser support for CSS was, to be blunt, pretty dire. We could style pages with CSS to an extent, but browser inconsistencies made it difficult to do all but simple styling, like colors and fonts. IE 5 for the Mac faced a major challenge when it was launched. If it used a strictly standards-driven approach to rendering web pages, the vast majority of websites online at the time (most of which had been authored to suit buggy browsers) would appear “broken” in IE 5. Alternatively, if IE 5 simply rendered all pages as the older, buggy browsers did, there really wasn’t any point to its support for CSS standards. So IE 5’s makers developed a technique that would allow the best of both worlds.

They introduced the concept of two rendering modes: a standards mode, which provided full standards support, and a non-standards, or Quirks mode, in which the browser tried to emulate the broken rendering of older browsers. The browser developer’s biggest challenge was figuring out how the browser could determine which mode to use for a particular site.

The ingenious hack (in the good sense of the word) that they hit on was the observation that the developers who used a document type in their pages tended to be the same developers who designed with standards in mind (DOCTYPEs, which we saw in Chapter 3, were then considered an optional extra and were only widely used by standards-focused developers). The combination of IE 5’s excellent support for CSS rendering and its ability to switch modes is probably one of the most significant steps in the evolution of the standards-based web, though ironically the whole concept of using DOCTYPEs in this way is still viewed critically in some quarters as being nonstandard. Over time, other browsers, including Internet Explorer versions 6 and higher for Windows, adopted the concept of Quirks mode and DOCTYPE switching.

Rendering modes, useful as they once were, have served their purpose, and are no longer really needed. Quirks mode was always intended to be used for older content, with the presumption that newer content should be written in conformance with standards. Still, these modes do exist, and we need to actively let browsers know we want to use standards mode.

Choosing Standards Mode

Any HTML document with a full DOCTYPE will be rendered by all modern browsers (back to IE 6 for Windows) in standards mode. With rare exceptions, this is the mode you should use. In IE 6 and up, Quirks mode effectively triggers the same rendering as IE 5.5 for Windows, which is a huge leap backward. In other browsers, such as Opera, Safari, and Firefox, Quirks mode causes yet another set of rendering behaviors that certainly won’t be identical to one another or to that of IE 5.5. Quirks mode is triggered by using no DOCTYPE or a DOCTYPE with no URL. For example, this DOCTYPE:

image

will cause any browser to render the document in standards mode.

On the other hand, this one:

image

will cause browsers to use Quirks mode, as will leaving off the DOCTYPE entirely (which we’d never do, since it would prevent us from validating our pages). With Internet Explorer, there are additional constraints: if anything (such as a comment) precedes the DOCTYPE declaration, IE will use Quirks mode:

image

Lastly, if you want to trigger Quirks mode only in IE 6, you can add an XML prolog to an XHTML document, like this:

image

IE 8’s New DOCTYPE Switching Model

Internet Explorer 8 has introduced a new DOCTYPE switching model, which caused considerable controversy before the browser’s launch. The fuss has since died down, but “compatibility mode switching” in IE 8 (and in future versions of IE) is more complicated than DOCTYPE switching. Firstly, IE 8 supports several compatibility modes:

• IE 5 mode—Essentially the same as IE 7 in Quirks mode

• IE 7 mode—A mode that renders content “as if it were displayed by the Internet Explorer 7 standards mode.” This is often referred to as “almost standards mode.”

• IE 8 mode—Internet Explorer’s current top-of-the-line page rendering

To tell the browser which mode we want it to use, we’ll need to use a new meta element—X-UA-Compatible—with various content values to tell IE 8 (and newer browsers) which rendering engine to use. The meta element appears in the head of a document before any elements other than title and other meta elements; it comes before any link or script elements. Its http-equiv attribute value is X-UA-Compatible, and its content attribute tells IE which rendering mode to use:

image

It’s also possible to specify the same information via an http header by setting this up in your web server (such as Apache or IIS).

The possible values of the content attribute are:

IE=5 (aka Quirks mode)—IE will use the IE 5 rendering model, regardless of the DOCTYPE.

IE=7 (also known as IE 7 standards mode)—IE will use the IE 7 in standards mode rendering model regardless of the DOCTYPE.

IE=EmulateIE7 (IE 7 emulation mode)—IE will use IE 7’s standards or Quirks mode, depending on the DOCTYPE (essentially the browser pretends to be IE 7).

IE=8 (IE 8 standards mode)—IE will use IE 8 standards mode, regardless of the DOCTYPE.

IE=EmulateIE8 (IE 8 emulation mode)—IE will use IE 8’s standards mode or Quirks mode, depending on the DOCTYPE.

IE=edge (“latest mode”)—IE, from version 8 and up, will always use the latest standards mode regardless of the DOCTYPE.

There are further potential complications, but they’re rarely a problem, and you can follow up on them if you need to using the Resources section at the end of this book.

So what does this all mean? Essentially, you can choose to target different rendering modes using a combination of X-UA-Compatible instructions and DOCTYPEs. Which should you use? In an ideal world, you should use standards mode for newly developed sites, so IE=8 is the recommended mode—Microsoft advises against using IE=edge except in experimental projects. If you need to use a particular rendering engine for legacy content, you can use the various values of the content attribute as outlined.

What happens if no X-UA-Compatible meta element is present? Then matters get really complicated, and depend on such factors as whether users have chosen Compatibility View in their browsers, whether Microsoft has added your site to a list of sites for which they maintain compatibility information (typically only heavily trafficked sites), the air-speed velocity of an unladen swallow, and other factors. (OK, not the swallow thing, probably.) The best thing to do is include an X-UA-Compatible meta element or serve your pages with an X-UA-Compatible http header.

Common Browser Bugs

Here we’ll delve into a number of the most common browser rendering bugs, possible workarounds, and other solutions. Some of these, like the Box-Model Bug, will only show up in Quirks mode, and we only look at these bugs if they are historically significant. Why cover them at all? Because these bugs and their workarounds have had such an effect on web development that developers, even if they never need to deal with the bugs themselves, will likely be seeing leftover workaround code in legacy markup for years to come.

The Box-Model Bug

Probably the most vexing of all browser bugs is the Box-Model Bug in Internet Explorer 5 and 5.5, and in Internet Explorer versions 6 and higher in Quirks mode. The good news is that it’s easily avoided using standards mode rendering. But for historical purposes, let’s take a quick look at the bug that launched a thousand hacks.

If I specify the following CSS rule:

image

...then how wide should the p element be when rendered? (For now, we’ll leave aside the issue of whether we should be specifying all those values in pixels.) The obvious—and wrong—answer is 200px. It’s wrong because, according to the CSS specification, the element should be 254px wide, counting from the left edge of the left margin to the right edge of the right margin [7.1]. This might seem counter-intuitive, but the CSS specification says that width applies to the content of an element—and padding, margins, and borders are all added to make the total width of the element. The same approach applies to the height property.

7.1 The standard CSS box model

image

Internet Explorer 5, 5.5 (and later versions in Quirks mode) calculate the width of an element differently. Given the CSS just provided, these versions of IE would calculate the width of the element as, logically enough, 200px, making the content box 146px wide (200px minus 40px for the margin, 10px for the padding, and 4px for the border) [7.2]. This method may seem more logical, but width in CSS applies to the width of the content, not the whole width of the element (though with the CSS3 box-sizing property, it’s now possible to specify the box-model calculation to use either the standard model, or the IE model).

7.2 The IE CSS box model

image

In many situations—and particularly with the float-based multi-column layouts discussed in Chapter 9—this discrepancy is highly detrimental to the sanity of web developers. So what are we to do about it? Fortunately, the bug vanishes if we use a full DOCTYPE and thus trigger standards mode, in which all versions of IE since version 6 use the standard box model. Before later versions of IE provided this solution, many hacks were developed to address this problem, and we’ll look at a few that are relevant to developers who must maintain legacy code.

The Doubled Float-Margin Bug

Fixed in IE 7, the IE Doubled Float-Margin Bug once wreaked havoc on float-based multi-column layouts as they came into prominence. In a nutshell, in certain situations, the horizontal margin between a floated element and the element in which it is floated is doubled, and thus takes up twice the amount of room specified in the CSS [7.3].

7.3 In IE 6, the horizontal margin between an element and the edge of the element within which it floats is sometimes doubled by this bug.

image

The fix, should you require one, is straightforward—just set the floated element’s display property value to inline. This will have no effect in other browsers, because inline elements, when floated, automatically become block-level elements. But in IE 6, simply adding this value to all floated elements fixes the problem.

The Non-Collapsing Margins Bug

Just as the standard box-model calculation of width and height may seem counter-intuitive, so too is what happens to adjacent vertical margins on elements. As we saw in Chapter 3, when two vertical margins of block-level elements touch, and the elements don’t have padding or borders adjacent to the vertical margins, these margins should collapse so that the combined margin is only the size of the larger of the two margins [7.4].

7.4 In the absence of padding or borders, adjacent vertical margins should collapse.

image

As you may have guessed, Internet Explorer 6 and 7 don’t always collapse adjacent vertical margins, even if you trigger standards mode: when certain properties are applied via CSS, the margins just don’t collapse. This has to do with a magical IE-only property of HTML elements, hasLayout, which is part of no standard, but which Internet Explorer uses as a built-in or internal property when it renders pages. Some CSS properties, including width, height, position: absolute, float, and display: inline-block, give their associated element a hasLayout property with a value of true. Some HTML elements, including html, body, img, and many table- and form-related elements, have this property by default. When an element has a hasLayout property with a value of true, its vertical margins won’t collapse when they should.

It’s nearly time to jump in and look at workarounds for this and other bugs—but first, we need to take a detour and learn more about the wonderful world of hasLayout.

IE and hasLayout

Over the years, Internet Explorer 6 and (to a lesser extent) 7 have caused a lot of layout problems. Over time, intrepid developers including Holly Bergevin and John Gallant discovered that IE’s internal hasLayout property is behind many of these problems. Although this is mostly a legacy problem, we’ll take a brief look at hasLayout in case you have to deal with it in the coming years.

Deep Within Your Browser

Internally, the rendering engine of Internet Explorer for Windows (known as Trident) manages the layout of the page in part using the hasLayout property. Because—as mentioned earlier—hasLayout is not part of any standard, developers shouldn’t really need to worry about it. But this property can have significant consequences for page layout. In a nutshell, when an element has a hasLayout value of true, then it is responsible for its own layout, and the layout of its descendent elements (except for those which have hasLayout). If an element has this property set to false, then its layout is determined by the nearest ancestor element with hasLayout set to true.

In practical terms, when an element has a hasLayout value set to true, many of the common Internet Explorer (6 and to a lesser degree 7) layout bugs go away. Occasionally, particularly in IE 6, an element having layout causes browser bugs. As mentioned, with the release of IE 8, this issue has largely been relegated to one of historical interest, and even with IE 7 was much less of an issue than in IE 6. But it’s something developers should know about, as much as anything to understand strange features of some legacy CSS which exist to circumvent these problems.

How Does an Element Get Layout?

There are two ways in which an element can get layout (the term developers use for giving an element’s hasLayout property a value of true). It can either be one of a number of elements that have this property value by default, or it can have certain CSS properties set for the element. The following elements have a default hasLayout value of true:

applet

body

button

embed

fieldset

html

hr

img

input

legend

object

table (and td, th, and tr)

textarea

select

Several CSS properties can also cause an element to get layout. These properties include:

float (of left or right)

min-width, max-width, min-height, and max-height (IE 7 only)

overflow (IE 7 only)

position: absolute

position: fixed (IE 7 only)

width or height with values other than auto

zoom (this is a nonstandard, IE-only CSS property)

Fixing (and Triggering) Bugs with hasLayout

Setting hasLayout to true for elements associated with layout rendering bugs is widely considered to be a cure-all for many such bugs. Nevertheless, because hasLayout is an internal feature of Internet Explorer, developers’ understanding of the property is based on reverse-engineering, and is necessarily imperfect.

Many bugs are fixed by giving layout to an element—usually the element that contains the page’s floated elements. You can often do this safely in IE 6 and 7 by giving the element one of the standard CSS properties and values listed above, or by conditionally linking to an IE-only style sheet and giving an element a zoom property value of 0.

To fix other bugs, such as the Non-Collapsing Margins Bug mentioned earlier in this chapter, we need to set the hasLayout property to false (thus taking layout away). But there’s a catch: because hasLayout is not a CSS property, we can’t use CSS to set hasLayout to false—nor can we do it via JavaScript. We can set the hasLayout property value to false for elements that do not have layout by default simply by not using any of the previously listed CSS properties that set hasLayout to true. But we can’t set hasLayout to false for elements that do have it by default. Fortunately, elements that do have layout by default are rarely the elements that cause problems like the Non-Collapsing Margins Bug.

Although giving an element layout can make page layouts more stable in IE, it can also introduce a serious float-related bug: when a block-level element has layout and an explicit width and an element is floated beside it, rather than the content of the element flowing around the floated element, this element stays completely rectangular, and is itself displaced [7.5].

7.5 When a block element with a hasLayout value of true has an element floated by its side, rather than its content flowing around that element (right), it remains rectangular and is displaced by the floated element.

image

As you may have guessed, the whole problem is complicated, and a close examination is beyond the scope of this book. Fortunately there’s a very detailed discussion at Position Is Everything (www.positioniseverything.net/explorer/floatmodel.html), a fantastic resource for understanding and working around browser bugs.

Other (In)famous hasLayout Bugs

Internet Explorer has the distinction of having whole websites like www.positioniseverything.net devoted almost entirely to its rendering quirks—and of having loads of bugs with idiosyncratic names documented and dissected all over the web. Before we leave hasLayout behind, here are three more notes about the bugs it’s often used to cure:

• The 3-Pixel Text Jog Bug, which shows itself in some floated contexts, is fortunately cured by giving layout to the containing element of the floated element.

• The Peek-A-Boo Bug is difficult to pin down, and fortunately appears only in IE 6. It causes text with a floated element alongside it to simply vanish, then strangely appear when the page is scrolled, and in other circumstances that cause the window to be redrawn. Giving layout to the containing element of the floated element usually fixes the problem.

• The Double-Margin Float Bug, which we just discussed, can also be fixed by giving layout to the floated element.

Bug Fixing: To Hack or Not To Hack?

In many ways, “hacking” is at odds with the concept of progressive enhancement. Hacking is all about making websites look the same in every browser, usually at the cost of considerable effort, while the goal of progressive enhancement is to deliver information and features to browsers based on their capabilities. But getting pages to look the same across browsers is still an unavoidable necessity in many real-world projects, and some bugs are such showstoppers that we need to deal with them. So how should we go about working around browser bugs?

The traditional approach has been to use hacks with names like the Tantek (Box-Model) Hack, the Holly Hack, the Tan Hack, and so on. These methods, however, are increasingly of historical interest only, and typically rely on the fragile strategy of using one bug in a browser to work around other bugs in the same or different browsers. This method is fragile because if the bug we are trying to avoid gets fixed, but the bug we are relying on as a workaround doesn’t get fixed, our CSS must be rewritten. Worse, if the bug we are relying on as a workaround gets fixed, but the original rendering bug remains, our pages will break—and again, our CSS will have to be rewritten.

Instead of using hacks, when we need to specifically target a particular browser—either to provide browser-specific CSS to it or to hide CSS from it—we can break out this CSS into separate style sheets and use more stable workarounds. For example, consider the famous Box-Model Hack (more on that soon), which delivers different widths to different browsers by relying on parsing bugs in Internet Explorer 6. It looks like this:

image

These days, we’d be better off putting the IE-specific styles into a separate style sheet and linking to it in such a way that other browsers will not see the link.

So, in our IE-specific style sheet we’d have

image

while in our “regular” style sheet we’d have

image

Know Your Enemy

Because there is a great deal of code out there that uses these sorts of hacks, here’s a quick summary of the functions and uses of web development’s most common hacks. Again, you shouldn’t be using these in new sites, but you may find examples of them in your code if you’re maintaining large, aging code bases, so some knowledge of the techniques is worth having.

Selector-Parsing Hacks

Selector-parsing hacks rely on the absence of support for some types of CSS selectors in certain browsers (usually IE), and thus allow developers to hide specific statements from those browsers by using a selector that the browser doesn’t support. For example, IE 6 doesn’t support the universal (*) selector. So adding * to a selector hides the statement from Internet Explorer. If we wanted to specify a width of 400px for a particular element for IE versions 6 and older, and a width of 300px for all other browsers, we could use this CSS:

image

The rules of CSS specificity say that the second statement takes precedent over the first, so browsers that recognize the selector * .content will apply a width of 300px to elements with a class value of content. IE 6 ignores that statement, because it doesn’t recognize the universal selector.

There are other well-known selector patterns for other versions of IE, but again, this method relies on two bugs working in tandem (or being fixed in tandem in future browser versions), so it’s too fragile to use in most production code.

Statement-Parsing Hacks

The original hack used for targeting CSS to a particular browser was devised by Tantek Çelik, who led the development of the rendering engine in IE 5 for the Mac. Çelik’s extremely clever hack, which we saw earlier, relied on a somewhat baffling CSS-parsing bug in IE for Windows. Subsequently, other, more compact hacks have been developed which rely on the same principle, which is that a parsing bug in a browser makes them ignore perfectly valid (if usually odd-looking) CSS.

Today, the Box-Model Hack is mostly used to work around the Box-Model Bug in older IE versions (and in Quirks mode to this day). Here’s the CSS rule again:

image

Its distinctive markings are obvious from a mile away: it uses the voice-family property of CSS to trick IE’s parser into thinking that the statement is broken. When parsers detect an invalid property declaration in a statement, they must skip to the next statement. Because IE 6 and 7 wrongly consider the first voice-family declaration to be invalid, they miss the second width declaration entirely.

Because it relies on a pair of bugs (one that causes a problem and one used to fix it), this and other statement-parsing hacks are just as fragile as selector-parsing hacks, and should also be used with extreme caution, if at all.

So, given that it’s strongly recommended to avoid all such hacks, how should we target specific browsers? Read on to find out.

Targeting Browsers

Sometimes it is necessary to serve specific style sheets to specific browsers—or to hide certain style sheets from certain browsers. It may be because we wish to serve minimal styles to an older browser, or because we want to group together all the workarounds specific to a browser in a single style sheet for easier maintenance (and to avoid using statement-level hacks like the ones we’ve just looked at).

There are two principal ways of serving or hiding specific style sheets. We’ll classify these as workarounds, rather than hacks, for a couple of reasons: First, they don’t rely on complementary bugs in the way that the hacks we’ve just considered do. Second, the “bugs” they rely on either won’t be fixed (for example, a bug in Netscape 4) or aren’t bugs at all, but features designed to work precisely as we are about to use them.

The first of these workaround techniques relies on legacy browser bugs, such as Netscape 4’s lack of support for the @import statement. The second, conditional comments, is specific to Internet Explorer, and allows for linking to style sheets that only Internet Explorer will pay attention to (with conditional comments, you can even target specific versions of IE).

Hiding Style Sheets from Older Browsers

One approach to managing the poor support for modern CSS in older browsers is to hide most or all your CSS from these browsers. Although the idea of serving a very minimal style to older browsers is unnerving to some developers, anecdotal evidence suggests that users of these older browsers—who are also highly likely to be using older computers and operating systems, and to have slower network connections—actually often appreciate these less heavily styled pages, which download more quickly and don’t tax their limited system resources.

Hiding Styles from Netscape 4

Netscape 4 doesn’t support linking to style sheets with the @import rule. So, instead of linking to a style sheet with a link element in the head of a document, we can link using an embedded style sheet in our document that contains an @import rule—or use an @import rule in an external style sheet—and then put any style we want to hide from Netscape 4 in the imported style sheet. So instead of a simple linked style sheet like this:

image

We might separate out CSS into two style sheets—one containing core style for all browsers, and one for non-Netscape browsers—and use this code:

image

Alternately, we might link to a style sheet and place the @import statement in the linked style sheet.

A related technique is to link to external style sheets with a media type of all, like this:

image

Netscape 4, and some old versions of Internet Explorer, will ignore these links. There’s some suggestion that @import statements can impact page loading performance, so the second of these two methods would be recommended.

Conditional Comments for IE

Microsoft implemented a feature in Internet Explorer that lets developers target specific pieces of HTML to specific versions of IE while hiding it from all other browsers using conditional comments. The contents of conditional comments are ignored by other browsers, but are visible to various versions of IE, depending on the form of the comment, and although conditional comments only apply to HTML, we can give specific versions of IE-specific style sheets by using conditional comments in conjunction with the link element in the head of an HTML document.

Here’s how conditional comments work. Regular HTML comments look like this:

image

Conditional comments use this syntax and extend it to add instructions telling Internet Explorer to either use or ignore the contents of the comments; other browsers will continue to ignore them just as they ignore other HTML comments. Conditional comments specify a target in square brackets right after the opening of the HTML comment. For example, to target only IE 6, we’d use a comment like this one:

image

We can use the following targets in conditional comments:

[if IE]—will be used by any version of IE from 5 and up (conditional comments were introduced with version 5)

[if IE 5], [if IE 7] and so on (note the space between IE and the browser number), targets specific browser versions

[if gt IE 6] (gt stands for greater than—this example targets versions after version IE 6)

[if gte IE 7] (gte stands for greater than or equal to—this example targets version IE 7 or more recent)

[if lt IE 8] (lt stands for less than—this example targets versions of IE older than IE 8)

[if lte IE 6] (lte stands for less than or equal to—this example targets IE 6 or older)

Conditional comments can only be used inside HTML—we can’t conditionally comment our CSS with this approach. So, we can’t say something like this inside a linked style sheet:

image

Conditional comments are less fragile than hack-based techniques for working around browser limitations and bugs, although they’ve been less popular than hacks, probably because they require developers to separate out styles for Internet Explorer (or for specific versions of IE) into their own style sheets, which can complicate code maintenance. As with all workarounds, they need to be used as sparingly as possible, and style sheets linked using these techniques should be very well documented so that the interaction between statements and properties in different style sheets is clearly noted. For example, if we are specifying a width for IE browsers in one style sheet, and all other browsers in another, it would make sense to note this in the respective style sheets like this.

In the style sheet only for IE 6 and older:

image

In the style sheet for all other browsers:

image

When Feature Support Is Missing

The techniques we’ve covered so far deal with browser inconsistencies due to buggy support for CSS in one or more browsers and good support in others. The second significant challenge developers face is the absence of support in one browser for a feature that is supported in other browsers. This is more common as Firefox, Safari, and Opera introduce support for CSS3 features and Internet Explorer continues to offer limited CSS3 support. (We look in detail at CSS3 in Chapters 12 through 15.)

In many cases, progressive enhancement is the way to go. If a browser doesn’t support border-radius, text shadows, box shadows, or other CSS3 features, we can usually just ignore the lack of support for such cosmetic properties. But, there are often features that go beyond the cosmetic—in particular, CSS3 selectors—that are well supported in browsers other than Internet Explorer, and which can radically improve the quality of our markup (as we’ll see in Chapter 12). In the absence of support for such features in a widely used browser like IE, can we use them at all?

Happily, the answer is yes. Using JavaScript—and popular JavaScript libraries whose use requires little actual scripting knowledge—we can add support for many features that are not natively supported in web browsers. Let’s take a look at some of these libraries.

Dean Edwards’s IE 7 (and IE 8)

The best known JavaScript library for enhancing IE 6 and 7’s support for features of CSS2 and CSS3 is Dean Edwards’s ie7-js (code.google.com/p/ie7-js), which was originally known simply as “ie7.” This popular library has been updated and is now offered as a superset library, ie8-js, which includes all the functionality of ie7-js and adds support for IE 8 and features of CSS (and HTML) still missing even from IE 8.

The library’s goal is “to make Microsoft Internet Explorer behave like a standards-compliant browser,” and it adds support for:

• CSS selectors like the child, adjacent sibling, structural, and attribute selectors

• CSS properties including max-width, min-width, max-height, and min-height

• Alpha transparency in PNG graphics

...as well as fixing common bugs like the Double Margin and Peek-a-Boo bugs we saw earlier in the chapter, via a related bug-fixing library, ie7-squish.

When introduced, the idea of JavaScript libraries for extending and fixing browsers was quite radical, but in the years since ie7-js was first released, the idea of using JavaScript for this sort of purpose has become widely accepted. Still, two possible drawbacks remain. First, many people still use the web with JavaScript disabled, either because of personal security concerns or because of security policies in large corporate, government, and institutional networks. Because of this limitation, all JavaScript libraries should be used in conjunction with unobtrusive scripting techniques like those discussed in Chapter 5. The second potential drawback is that use of the library may harm site performance, particularly for very high-traffic sites. If you use one of these libraries in a production environment, you’ll need to consider the potential negative performance effects for your specific project.

Both ie7-js and ie8-js are easy to use. They’re hosted on Google Code, so in many cases you won’t even have to host them yourself. It’s a good idea to use conditional comments to link only to Internet Explorer, so that other browsers don’t download the unnecessary file. Here’s what that might look like if we wanted to use the ie8 version of the library along with the ie7-squish bug-fixing library:

image

And presto! Internet Explorer now supports all of the features that the library adds as though that support were native in the browser. These libraries are used on large, popular websites, and have been refined over several years, so they’re safe to use in just about every situation. The only real surprise is that more developers don’t use them.

The Wrap

Even a few years ago, if you had asked developers—even most standards-oriented developers—they’d probably have told you that they developed sites first to work perfectly in Internet Explorer, and then worried about validation and support in other browsers. Today, the tide has turned. Developers overwhelmingly develop to the standards first and then work on support for various browsers.

Only a few years ago, the web developer’s lot was that of a constant battle with browser bugs and inconsistencies. Although it may sometimes still seem so today, the reality is that browser support for CSS and other standards has improved dramatically in all browsers. We’ll still be dealing with browser inconsistencies for some years to come, but if the improvements of the last few years are any indication, this will become less and less a concern. With luck, this chapter will soon be outdated—used only to help new developers understand what that strange-looking CSS in their ancient legacy was actually for, back when it was still needed.

We live in hope.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset