Saturday, January 30, 2010

CSS Browser Compatibility Tricks 5b

******************************************

Quirks Mode

===========

Modern browsers have at least two modes in which they can display content:

1. Standards-compliant mode

2. Quirks mode

In standards-compliant mode, the browser does its best to display the page according to the latest CSS standards. In quirks mode, the browser displays the page as if it were an older version of the same browser. The purpose of quirks mode is to make pages that were designed for the old browsers display the same in the newer browsers.

You won't find much difference between quirks mode and standards-compliant mode in Mozilla, Opera or Safari, but you may see big differences in Internet Explorer.

******************************************

Turning Off Quirks Mode

=======================

By default, quirks mode is on. It can be turned off by adding the correct DOCTYPE declaration at the top of the HTML page. The following DOCTYPE declarations will turn on standards-compliant mode for all modern browsers:

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

"http://www.w3.org/TR/html4/loose.dtd">

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

"http://www.w3.org/TR/html4/strict.dtd">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

One gotcha(disadvantage) in Internet Explorer is that quirks mode is always enabled if you include an XML declaration (<?xml version="1.0"?>), so we recommend you do not include one.

Quirks mode provides an excellent means of testing how pages will look on different browser versions

******************************************

Design Strategy or Steps

========================

When designing your pages, we recommend you use the following strategy:

1. Design for the most standards-compliant browsers first (e.g, Firefox).

2. Check your pages in the latest version of Internet Explorer and fix any bugs. We'll discuss the best way to isolate this code shortly.

3. Check your pages in Internet Explorer using quirks mode by temporarily cutting the DOCTYPE declaration and fix any bugs.

Depending on your need to support other browsers, you may wish to repeat steps two and three on those browsers as well.

******************************************

Internet Explorer Conditional Statements

========================================

Internet Explorer provides a way of adding conditional statements that allow the designer to specify which version(s) of the browser should display certain sections. These conditional statements appear as simple HTML comments to other browsers (e.g, Firefox) and are therefore ignored. This can be very useful for addressing CSS bugs in older versions of Internet Explorer without having any impact on other browsers.

The syntax is shown below.

Syntax

<!--[if IE 7]>

HTML Code only shows up on Internet Explorer 7

<![endif]-->

As you can see, the beginning if statement starts with the beginning of an HTML comment (<!--) and the endif statement ends with the end of an HTML comment (-->), so all other browsers view the whole contents as a comment and do not render any of the contained code.

The code shown above will only be displayed in Internet Explorer 7, but you can use operators to specify multiple versions that will display a block of code. The operators are shown below:

! --> not <!--[if ! IE 7]>

lt --> less than <!--[if lt IE 7]>

gt --> greater than <!--[if gt IE 7]>

lte --> less than or equal <!--[if lte IE 7]>

gte --> greater than or equal <!--[if gte IE 7]>

Note that these conditional comments can not be embedded within CSS.

The following is invalid:

-------------------------

<style type="text/css">

.MyStyle {

background-color: red;

<!--[if lt IE 7]>

background-color: blue;

<![endif]-->

}

</style>

You would instead structure this as follows:

--------------------------------------------

<style type="text/css">

.MyStyle {

background-color: red;

}

</style>

<!--[if lt IE 7]>

<style type="text/css">

.MyStyle {

background-color: blue;

}

</style>

<![endif]-->

The following example shows how you might structure an HTML page using Internet Explorer's conditional comments to deal with IE-specific bugs.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<link href="main.css" rel="stylesheet" />

<!--[if IE 6]>

<link href="ie6.css" rel="stylesheet" />

<![endif]-->

<!--[if lt IE 6]>

<link href="ie5.css" rel="stylesheet" />

<![endif]-->

<title>Conditional Comments Structure</title>

</head>

<body>

</body>

</html>

Code Explanation

----------------

The advantage of such a structure is that it separates the CSS hacks from the main style sheet, so main.css should standalone as a nice clean CSS file that works great with the browsers that support the standard well.

******************************************

Common Browser Bugs / Issues

============================

1. Positioning Legends

2. Double-Margin Bug

3. Float-Width Bug

4. 3-Pixel Gap Bug

5. IE 5 and 5.5 Box Model Bug

1. Positioning Legends

======================

The positioning of legends gets messed up in Internet Explorer when the border of the fieldset is set to 0. For example, take a look at the simplified form below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

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

<style type="text/css">

fieldset {

border:0;

background-color:#cee;

padding:10px;

}

legend {

font-weight:bold;

font-size:1.2em;

}

</style>

<title>Password Reminder</title>

</head>

<body>

<form method="post" action="action.php">

<fieldset>

<legend>Password Reminder</legend>

<label for="Email">Email:</label>

<input type="text" size="20" name="Email" id="Email" title="Email" />

</fieldset>

<fieldset id="buttons">

<input type="submit" id="Submit" name="Submit" value="Login" />

</fieldset>

</form>

</body>

</html>

* Firefox and Safari shows a similar result.

* But Internet Explorer moves the legend down.

This can be fixed using relative positioning, with this code:

legend {

position: relative;

top:-.6em;

}

But if we put that into the general rule for legend,

it will mess up other browsers, so we need to use an

Internet Explorer conditional comment:

<!--[if IE]>

<style type="text/css">

legend {

position: relative;

top:-.6em;

}

</style>

<![endif]-->

And now the legend will look similar in all browsers.

2. Double-Margin Bug

====================

The double-margin bug manifests itself in Internet Explorer 6 and earlier when an element has a margin in the same direction in which it floats (e.g, a left margin on an element that floats left). In this case, IE 6 and earlier double the margin as shown in the example below.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Double Margin</title>

<style type="text/css">

#SideBar {

float: left;

margin-left: 50px;

width: 200px;

background-color:green;

}

#MainPage {

float: left;

width: 400px;

background-color:yellow;

}

---- Code Omitted ----

</style>

</head>

<body>

<div id="SideBar">

This is the side bar.

</div>

<div id="MainPage">

This is the main page.

</div>

<div id="w50">--50px wide--</div>

<div id="w100">--100px wide--</div>

</body>

</html>

The fix is very strange: you simply set the display property of the offending element (in this case, the sidebar) to "inline". Because here all floats are block elements(div mainpage,w50 and w100), doing so has no effect on the display in other browsers; however, it does, for some reason, fix the display in Internet Explorer.

Although you could make this fix directly in the SideBar rule, we recommend separating it out into an IE-specific stylesheet with conditional comments as shown below.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Double Margin</title>

<style type="text/css">

#SideBar {

float: left;

margin-left: 50px;

width: 200px;

background-color:green;

}

---- Code Omitted ----

</style>

<!--[if IE]>

<style type="text/css">

#SideBar {

display:inline;

}

</style>

<![endif]-->

</head>

<body>

<div id="SideBar">

This is the side bar.

</div>

<div id="MainPage">

This is the main page.

</div>

<div id="w50">--50px wide--</div>

<div id="w100">--100px wide--</div>

</body>

</html>

3. Float-Width Bug

==================

When a floating element is followed by a block-level element with a width defined, Internet Explorer incorrectly redefines the content area for the block-level element. To understand this, let's first look at how it is supposed to work.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Float</title>

<style type="text/css">

#SideBar {

float: left;

margin-left: 50px;

width: 200px;

border:1px solid green;

display:inline;

}

#MainPage {

border:1px dashed red;

}

</style>

</head>

<body>

<div id="SideBar">

This is the side bar.

</div>

<div id="MainPage">

This is the main page. This is displayed correctly in all modern browsers.

</div>

</body>

</html>

Block-level elements that come after the float are supposed to simply ignore the float; however, their inline content should not pass (not ignore) the float. The result is shown in Firefox and Internet Explorer below.

This is handled correctly in both browsers. The problem arises when a width is added to the block-level element. Internet Explorer 5.5 and earlier handle this by changing the available content area to start at the right side of the floating div, rather than the left side of the viewport (the browser window). To illustrate, let's add a width of 100% to the block-level element, which is called MainPage:

This should not change anything as the default width of an element is always 100%. However, IE 5.5 and earlier will render this page incorrectly.

Internet Explorer 6 and 7 correctly set the 100% width, but clear the element when the width is set (see float with width).

There is no simple solution to this problem. One option is to not define the width of the element that follows the float and to handle its positioning using margin-left (see Float With MarginLeft). Another option is to float the second element as well and then use margin-left to create a buffer between it and the preceding element (see float with following float).

******************************************

4. 3-Pixel Gap Bug

==================

Internet Explorer has a weird bug, in which it adds a three-pixel margin between a floating element and the subsequent element. If the subsequent element has a width defined, Internet Explorer pushes the whole element to the right. If no width is defined, Internet Explorer just pushes the content to the right. Examine the code below.

#SideBar {

float: left;

margin-left: 50px;

width: 200px;

border:1px solid green;

}

#MainPage {

border:1px dashed red;

}

Notice the tiny amount of added space between the text "This is the main page." and the floating element. Well, that's picky! And really, it doesn't create much of a problem, until you add a width to the subsequent element:

#MainPage {

border:1px dashed red;

width:200px;

}

This may not be a problem either, except in the case of a very tight layout. Those extra three pixels could cause the MainPage element to clear down under the float, which would destroy the design.

Luckily, the fix is easy. Simply set the margin-right of the floating div to -3 pixels as shown below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Three Pixel Fixed</title>

<style type="text/css">

#SideBar {

float: left;

margin-left: 50px;

width: 200px;

border:1px solid green;

}

#MainPage {

border:1px dashed red;

width:200px;

}

</style>

<!--[if IE]>

<style type="text/css">

#SideBar {

display:inline;

margin-right:-3px;

}

</style>

<![endif]-->

</head>

<body>

<div id="SideBar">

This is the side bar.

</div>

<div id="MainPage">

This is the main page.

</div>

</body>

</html>

5. IE 5 and 5.5 Box Model Bug

=============================

IE 5.5 has very little market share now and most developers don't need to worry about it, but if you do, this is an important bug to know about.

The CSS Box Model requires that an element's padding, borders, and margins are added (seperately) onto its width property. So, an element defined as follows:

#Box {

width: 200px;

padding-left: 40px;

padding-right: 40px;

border: 10px solid black;

}

would spread 300 pixels from left to right. The width property itself only applies to the content area. IE5.5 and earlier handle this incorrectly. The padding and border-width actually eat into the width of the content area. In these browsers, this element would only spread 200 pixels from left to right. We can see this by using quirks mode.

First, take a look at the code below, which simply creates the above rule and then two other rules to reveal pixel width.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<style type="text/css">

#Box {

width: 200px;

padding-left: 40px;

padding-right: 40px;

border: 10px solid black;

}

#w200 {

width: 200px;

background-color:red;

color:white;

font-weight:bold;

}

#w300 {

width: 300px;

background-color:blue;

color:white;

font-weight:bold;

}

</style>

<title>Box Model</title>

</head>

<body>

<div id="Box">

Hi there!

</div>

<div id="w200">--200px wide--</div>

<div id="w300">--300px wide--</div>

</body>

</html>

The page will display correctly in IE6.0 and later as we are using standards-compliant mode.

However, if we remove the DOCTYPE declaration from the code and refresh the page, we'll see what the page would display like in older versions of Internet Explorer(in quirks mode).

As you can imagine, this can cause page layout headaches. There is a famous hack that solves this problem called the "Box Model Hack" Although the creators of this hack were certainly very clever, we don't recommend using it, because...

* the hack is ugly

* it will make your CSS invalid

* Internet Explorer's conditional comments allow for a much cleaner and better way for handling such inconsistencies among browser versions

So, we recommend you use Internet Explorer's conditional comments instead.

******************************************

NOTES

=====

1. In Mozilla, this will actually turn on a third mode called "Almost Standards Mode", which, as its name suggests, is almost the same as standards-compliant mode.

2. The double margin bug is fixed in IE7.

3. The "Float with Width" bug is fixed in IE8.

******************************************

Tags

----------

fieldset

legend

-------------

float with width

float with margin left

float with following float

******************************************

******************************************

No comments:

Post a Comment