Introducing IE8: The good, the bad, the (not so) ugly

Browsers come out every day. Webkit has a nightly build. Wireless devices come with their own, often unique, browsers. Even with the plethora of available browsers, Internet Explorer, a browser that is not regularly updated, has over 55% of the browser market. Internet Explorer 6 (IE6), which came out eight years ago, still holds 9% (between 6% and 18%, depending on where you look) of the browser market share. IE8 was released only in March 2009, and by July 2009, it already had 17.8% of the browser market share.

In this article, we take a look at the IE8 browser, and cover some tips and tricks to make sure your sites look good in both old and new browsers. Will cover many of the topics hilited below in greater depth in the next sections of the "Welcome to IE8" series.

CSS 2.1 Support

IE8 has complete support for CSS2.1. In fact, IE8 is the first browser to support all of the W3C CSS2.1 specifications. IE8 passes the Acid2 browser test. You can learn more about the Acid2 test from the web standards project. In brief, it’s test page designed to expose browser CSS2.1 rendering flaws, including testing transparent PNGs, generated content, the box model, and positioning, among others. While other browsers have been passing this test since 2005, Internet Explorer didn’t pass the Acid2 test until the release of IE8 on March 19, 2009. I guess late is better than never.

Internet Explorer 8 supports all CSS 2.1 Selectors

By having complete support for CSS 2.1, IE8 has a lot of improvements over IE7 and IE6 in terms of CSS support. We will take a look at the individual CSS2.1 selectors, and how IE6, IE7 and IE8 compare later in this series. The important things to note are that IE8 supports the :hover pseudo class on all elements, not just links as in previous versions. IE8 also supports the :before and :after pseudo-elements, along with the CSS content and counter properties and values. See CSS3 Selectors and Browser Support for a grid of both CSS 2.1 and CSS3 selector support in all grade A browsers. We’ll be covering all the CSS2.1 selectors in the next section of this series.

Internet Explorer 8 supports all CSS 2.1 Properties and Values

With IE8’s complete support for CSS 2.1, Microsoft Internet Explorer has finally entered the realm of "standards compliant" browsers. IE8 has made great improvements over IE7 and IE6 in terms of CSS property and values support, almost completely supporting the CSS 2.1 specifications. IE8, however, like IE7 and IE6, has no support for any CSS3 properties or values. We will take a deeper look at CSS2.1 properties and values later in this series. In addition to supporting the W3C boxmodel (padding, width, margin) which is discussed next, some hilites include IE8’s complete support of outline, content, z-index, border-spacing, caption-side and empty-cell and support for more values of the display, list-style-type and white-space properties. See my list of CSS properties and values and browser support for a more detailed list of all the properties, values and browser support. We’ll go into greater detail on some of these CSS improvements in the next sections of this series.

Internet Explorer 8 supports the W3C Box Model

Microsoft finally got the W3C box model correct. While you may disagree with the W3C box model, and may think Microsoft, not the W3C, got it right, it is important to follow the standards.

IE8 and all non-IE grade-A broswers use:

total width = margin-left + border-left + padding-left + width + padding-right + border-right + margin-right

but IE6 and IE7, when not in browser standards compliant mode use:

total width = margin-left + width + margin-right

If you really love the IE box model, you can still implement it with:

-ms-box-sizing: border-box;

That’s about all we need to know about the box-model and IE8, so I will not be elaborating on this in future sections.

IE8 Developer Toolbar

IE8 comes with a developer toolbar. The developer toolbar is an improvement on the debugging tools of previous IE versions. It’s an apparent imitation of the Firebug extension for Firefox, but not as robust. Similar to Firebug, you can highlight an element and can edit CSS on the fly. The CSS module informs you of inherited CSS and current values (in reverse order from Firebug). The CSS panel has check boxes next to each css property so you can turn on and off that property.

IE7 Compatibility View

The IE8 chrome provides a button to enable IE7 compatibility view. Compatibility View forces Internet Explorer 8 to display content as if the user were using IE7, with all of IE7’s quirks, hacks and errors.

The weird thing about using this button is that Microsoft actually keeps tabs on it: information is sent to microsoft whenever you press that button, unless you set your preferences otherwise, and lets MS know that "a lot of people are switching rendering modes" for that domain. Microsoft actually keeps a list of websites that these staticstics "prove to them" are best displayed in Compatibility View. Microsoft construes our clicking of that IE7 compatibility view button as feedback that the site doesn’t render right in IE8.

Forcing IE7 of IE8 rendering mode

As mentioned above, IE8 provides the user the ability to change how they view websites: providing the ability to switch back and forth between IE8 and IE7. You can override this, and force the site to be rendered either as IE8 or IE7 (your choice) within the IE8 browser, disabling the IE7 Compatibilty view botton.

To force IE8 rendering mode:

<meta http-equiv="X-UA-Compatible" content="IE=8" />

To force IE7 rendering mode:

<meta http-equiv="X-UA-Compatible" content="IE=7" />.

IE8 bugs

IE8 Disappearing Page Bug: If you put two adjacent nodes, both positioned absolutely, and set only one of x- or y- positioning, you may get a blank page.

IE8 CSS Hack

This IE8 CSS hack uses the star hack to target IE7 and lower, but you can use any other of the many IE hacks to target older IE browseres.

p.myclass {
color: green;
*color: red;
}
body:last-child p.myclass {
color: blue;
}

Conditional comments still work in IE8. Just note that if you used the conditional comment of

<!--[if IE]>
  IE only information here
</![endif]-->

The above will also be read by all Internet Explorer versions, past current and future. If you’ve included this in past websites, check to make sure your sites still work. If you find issues, simply change the [if IE] to [if lte IE7] for if less-than or equal to IE7.

Other Features:

  • Full ARIA (accessible rich internet applications) support
  • hasLayout is no longer a factor
  • <object> nesting, or fallbacks, has been implemented correctly. See the HTML Object element for more information.
  • Native JSON (JavaScript Object Notation) support
  • The ‘style’ property is available via the DOM
  • Supports getElementByName(‘formElementName’);
  • CSS styling of the <legend> element is now supported
  • Supports data URI schema value. Wikipedia does a good job of explaining data URI schema.

::before and ::after: Generating Content

In this section we learn about the different types of content that we can generated with CSS using the content property and its various value types. You’ve likely only touched upon the CSS content property, adding a simple string before or after an element. The content property can take many more values that just a simple string: you can add text, images, quotes, special characters, even images to your page using the content property to generate content in your :before and :after pseudo-elements. In this section we take a deeper look into the various values of the CSS content property.

Generated content is now supported in IE8 and all other modern browsers, so it makes sense to learn. There is an archaic table of browser support for the various values of the content property below (see listing 8).

Values of the CSS content property

The CSS content property can take as its value

  • none
  • normal
  • <string>
  • url
  • open-quote
  • close-quote
  • no-open-quote
  • no-close-quote
  • attr(attribute)
  • counter(name[, style]).

In this section of the series, we will discuss all of these values. We will only touch upon attr(attribute) and counter(name) in this section, as we will dive deeply into those two value options in the next section of this series..

Definition and purpose of each value of the content property

The CSS content property can take as its value none | normal | <string> | url | open-quote | close-quote | no-open-quote | no-close-quote | attr(attribute) | counter(name[, style]). Values have the following meanings:

  • content: none;

    none: When content: none; is included, the pseudo-element is not generated. This does NOT work in the current version of Safari (or Opera), nor is it expected to be supported in the next release of Safari. The solution to fix this which works in all modern browsers is to define the value as an empty string: content: "";. The two quotes with no content between the quotes is called an empty string. For example, some browsers automatically add opening and closing quotes to the <q> element. To override this default presentation, include q {content: "";} instead of q {content: none;}, so that all browsers override the default <q> presentation.

  • content: normal;

    normal: The ‘normal’ value, according to the W3C specifications, is supposed to “compute to ‘none’ for the :before and :after pseudo-elements.” To me, this specification is unclear. Is it supposed to compute to ‘none’ unless the default browser rendering includes content? The only element where interpretation of this value is relevant is the <q> or ‘quote’ element. In this case, the ‘normal’ value is handled differently in different browsers. Safari and Opera show the default content of quotes encompassing the text in between the opening and closing <q> tags. IE8 and Firefox do not show the quotes: computing to ‘none’. In the grid of support below I put support for Safari and none, and Opera as ‘iffy’, since my take is that Opera misinterpreted the deflation: Opera does compute to ‘none’ for most elements, but leaves quotes around the <q>, which is “normal”, but not the correct value for ‘normal’ according to the W3C.

  • content: "Estelle: ";
    content: "\00a3 "; /* includes '£' */

    string: The values of content can be a string encompassed in quotes. Including a string value will add your string before or after the element (depending on which pseudo-element is used). Strings can either be written with double or single quotes: the opening quote needs to be the same type of quote as the closing quote.

    If your string includes a quotation mark, make sure you escape it with a back slash. Otherwise, you can generally include any keyboard character. If you are putting a string of text, you may want to include a space in your text. You can also generate this spacing using CSS. Remember, as we learned in section 32, you can use CSS to stylize your generated text even though the generated text is NOT added to the pages document tree.

    Advanced topic: If you are going to include any non-ASCII characters or entities, declare the charset in your CSS and XHTML, and/or use the ISO / IEC 8859-1 (a.k.a. Latin-1) code for the character. Check out my blog post on including named entities in CSS and Javascript for examples and instructions.

  • content: url(myBullet.gif);

    url: You can add images as generated content (and even sound as generated content for auditory pages), by linking the content to an online file. To include an external file as generated content, include the URI inside the “url()”. The value of the property in this case it a path and file name that designates an external resource, such as an image, inside the “url()” as demonstrated above. If the browser can’t display the resource, FireFox and Internet Explorer 8 omit the file completely, as if it were not specified. Safari, on the other hand, indicates that the resource cannot be displayed with a missing image icon.

  • content: open-quote;

    open-quote and close-quote: These values are replaced by the appropriate string from the ‘quotes’ property. When including nested quotes, if the outer quotes are double quotes, generally, in literature, the inner quotes should be single quotes. The values of open-quote and close-quote are supposed to handle that scenario, but it doesn’t work cross browser. Firefox and Internet Explorer get these values right. Opera handles this, adding quotes, but does not nest quotes correctly. Safari ignores these values completely. Until Safari handles the open-quote and close-quote, values, I recommend using doing a double declaration. The first declaration should be a string with an escaped quote of your choosing. The second declaration should use the key terms of open-quote or close-quote, so the browsers that understand the declaration can nest correctly.

    p.quote:before {
       content: "\"";
       content: open-quote;
    }

    Listing 1: The first line in understood by all browsers supporting content, since all browsers support the string value. If a browser does not understand the “open-quote” value, the browser ignores the value and inherits the string value from line 1.

  • content: no-open-quote;

    no-open-quote and no-close-quote: Introduces no content, but increments ( or decrements) the level of nesting for quotes. As mentioned in the open-quote/close-quote section above, when quotes are nested in some languages, the type of quotation mark used changes depending on the level of nesting. This is when these values are relevant. Again, safari ignores the declaration. Opera, Internet Explorer 8 and Firefox get it right (though Opera doesn’t nest properly. The trick described in Listing 1 works here too, except serve an empty string, as in listing 2.

    p.quote:before {
       content: "";
       content: no-open-quote;
    }

    Listing 2: The first line in understood by all browsers supporting content, since all browsers support the string value. If a browser does not understand the “no-open-quote” value, the browser ignores the value and inherits the empty string value from line 1.

  • content: attr(title);

    attr(x): This ‘function’ returns as the content value a string with the value of the X attribute of the element on which the content attribute is applied. The attribute value will be elaborated on in the next section.

  • content: counter(subtitles, decimal);
    content: counter(headers) "." counter(subtitles) ": ";

    counter(name) or counter(name, style): The counter takes two parameters: the name, which you can reference to increment or reset, and the style, which, if not declared, defaults to “decimal”. While you can name the counter almost anything except ‘none’, ‘inherit’ or ‘initial’, avoid key terms. Counter will be elaborated on in the next section.

*By “modern browsers” I mean all browsers in listing 3 other than IE6 and IE7.

Browser support for the CSS content property and :before and :after pseudo elements

The CSS content property and possible values
IE6 IE7 IE7 in IE8 IE8 FF3 FF 3.5 Beta Saf 3.2 Saf 4 Beta Opera 9.64
:before
:after
content Since :before and :after is not supported in these browsers, testing is not possible, and moot. It is assumed that IE6 and IE7 does not support the content property, therefore supports none of these values works, except for issues below works, except for issues below works, except for issues below
none n
normal displays quotes on <q> Makes sense, but not the spec.
url() nothing nothing nothing missing image icon missing image icon missing image alt
string
open-quote

close-quote

Does not nest quotes correctly, but does include quotes.
no-open-quote

no-close-quote

attr(x)
counter

Listing 3: browser support for the various values of the content property.

 

CSS Background-Color Property

In this tutorial we will be looking at the background-color property, and how to apply it to elements in your web site. The ability to add colors to elements in your page by adding them to a style sheet enables you to create colorful designs while maintaining a consistent look and feel throughout the pages of a web site. We’ll review all the value types of the background-color property introduced in the past 3 sections. We’ll discuss including the background-color property within a style sheet, and problems that may arise depending on the browser.

background-color

The background-color property sets the background color of an element. When you don’t declare a background color, the default value is transparent. This attribute, like all other background attributes, is NOT inherited. All browsers support background colors.

selector { background-color: value;}

Listing 1: CSS syntax for background-color

You can add background color to any element within the body, the body, and the html element itself. Simply declare your color value as in the snippet of code above, where the selector is any CSS selector, such as class, id, tag name, or combination thereof. Use the property name "background-color", and one of the acceptable values described next.

background-color values

The background property can take many types of values:

  • Transparent
  • Color Name
  • RGB Value
  • Hexadecimal Value

Transparent

The default value for background color is "transparent". Since this is the default value and background-color in NOT inherited, you don’t have to declare it on any elements EXCEPT if you’ve declared that all elements of a type have some other background color, and in this particular case you don’t want that element to have that declared background color. For example:

p {background-color: #ff0000;}
p.nocolor {background-color: transparent;}

Listing 2: transparent is the default value, and should only be used with specificity to overwrite a more general declaration.

In this example, all paragraphs will have a background color of red, except paragraphs that have a class of "nocolor", which will not have a background color applied.

IE6 chokes on background-color: transparent when the transparency is applied to an element that is dynamically shown, such as on a drop down menu that is display: none, but is display: block when parent is hovered.

Color Name

There are the 16 colors defined in the W3C specifications. These include: olive, black, gray, silver, white, purple, fuchsia, aqua, navy, blue, teal, green, lime, yellow, red, and maroon. In section 24, Understanding Color Names, we discussed the 140+ color names that are supported by modern browsers, but, other than the 16 listed here, aren’t in the specifications. Feel free to use any of those color names EXCEPT "lightgray", which IE6 sometimes chokes on.

p {background-color: red;}

Listing 3: CSS syntax for background-color using color name

RGB (RGBA) Values

Colors are displayed by combining RED, GREEN, and BLUE light. In CSS, the levels can be defined by percentages or integers between 0 – 255. White can be written as rgb(255, 255, 255) or rgb(100%, 100%, 100%). Black can be written as rgb(0, 0, 0) or rgb(0%, 0%, 0%).

In browsers that support CSS3 (in other words, browsers other than IE), you can set the opacity or transparency level of the background color using background-color: rgba(255, 255, 255, 1);, where 255 is an integer between 0 and 255 or a percent value, and the 1 is any value between 0 and 1, with 0 being completely transparent and 1 being completely opaque.

Note: IE6 and IE7 get "partially compliant" for RGB, since they erroneously display color if integers and percents are mixed. This may be a good thing, but it’s not in the specifications.

Do not using mixed values in RGB, and do not use RGBA without browser targeting: both will fail in non-supporting browsers.

p {background-color: rgb(100%, 0%, 0%);}
p {background-color: rgb(255, 0, 0);}
p {background-color: rgba(255, 0, 0, 1);}

Listing 4: CSS syntax for background-color using RGB and RGBA. The three declarations above have the same value.

Hexadecimal Values

HEX values were discussed in Part 23: Understanding Hex Values. Hex values are the most common, best supported, and recommended way of including colors, including background colors, in CSS. To review, Hex color values are three double digit hexadecimal (hex) notations for the combination of Red, Green, and Blue color values (RGB) preceded by the hash (#) sign. Hex colors can also be written as three single digits.

Property Values for background-color

background-color: transparent;
background-color: rgb(255, 255, 255); 
background-color: rgb(r%, g%, b%); 
background-color: rgba(255, 255, 255, 1); 
background-color: rgba(r%, g%, b%, 1);  
background-color: #fff; 
background-color: #123456;
background-color: white;

Listing 5: Various ways of writing background-color property values.

Browser support for background-color

  Internet
Explorer 6
Internet
Explorer 7
Internet
Explorer 8
Firefox 2 FireFox 3 Safari 3 & 4 Opera 9.64
transparent Issues when dynamic
rgb(r, g, b) renders if value types are mixed renders if value types are mixed
#fff
#ffffff
rgba(r, g, b, a) ignores the entire call ignores the entire call ignores the entire call ignores the entire call ignores the entire call
Color Names OK, except for "lightgray"

Listing 6: Browser support for the various types of background-color property values.

For advanced users: DOM

For those trying to target the element using the Document Object Model, you can use:

document.getElementById("myID").style.backgroundColor

Listing 7: setting or extracting the background-color value using the DOM

HTML5: <section> v. <article>

I have been asked several times “when do you use <article> and when do you use <section> in HTML5?” I use an analogy that I figured I would share, as it seems to help developers make sense of the two elements.

Think of a newspaper. The paper comes in sections. You have the sports section, real estate section, maybe home & garden section, etc. Each of those sections, in turn, has articles in it. And, some of those articles are divided into sections themselves.

In other words, you can have parent <section>s with nested <article>s that in turn have one or many <section>s. Not all pages documents need these, but it is perfectly acceptable and correct to nest this way.

I hope that helps explain it.

-Estelle

The object element

The <object> element defines an embedded object. The <object> element is used to embed multimedia objects into web pages that are generally not natively supported by the browser. Object can be used for video clips, sound, images and other media formats. “Other media formats” include formats that are generally natively supported by browsers, such as images, text and html. The <object> element (and the various attributes) and child parameters provide browsers and multimedia application embedded in browsers with the information required to display multimedia objects.

<object data="myImage.png" type="image/png"></object>
<object data="myIframe.html" type="text/html"></object>
<object data="myMusicFile.mpeg" type="application/mpeg"></object>

Listing 1: the <object> element is a generic way of including media. Use more type specific elements, such as <img> or <iframe> when available. The <img> element is discussed in part 9 of this series.

The <object> element is generally used for embedding multimedia that requires the browser to load an external application to render the media (such as a flash movie or an audio file). The <object> element, along with its attributes and child <param> elements, allows you to specify everything required by the object — applets, plug-ins, media handlers and other components you may want to include in your web page — for presentation of that media by the browser and browser plugin, including source code, data type, initial values, etc. When including a Java applet, a .swf file, an ActiveX object, or other multimedia object, specify the data and parameters for objects and the code that can be used to display and manipulate the object data via <object> element attributes and child <param> elements.

Specifications and Browser Support

While the object element was supposed to be an important addition to the HTML 4.0 standard, it is still not completely supported by all browsers; though all browsers do support it to some extent. Whether an object is supported by the browser depends on the object type. The object element can be used to show many different media types such as ActiveX, PDF, Flash, or HTML, images and text files). Unfortunately, some browsers use different code to load the same object type. The nesting of the object elements is a great solution to enable you to degrade media based on browser support.

The <object> element can be located in either the <head> or as a child of the <body> element. The <object> can be found inside both block and inline elements, including inside the <button> and <a> elements, but NOT as a child of the <pre> element. The <object> element, in turn, can contain both inline and block level elements, including <param>, <form>, text and child object elements. While we’ll discuss <param> below, note that if a <param> element is found between the <object> and </object> it is part of the object of which it is a direct child and not an alternate code to execute. If text is found between the opening and closing <object> tags, it is alternate text for browsers that do not support the <object> element or the media defined by the <object> element. If the browser is able to display any of the parent media, then the text will not be displayed.

While the object element is an INLINE element, it can contain both inline and block level elements. Because it is an inline element, some recommend only including inline elements as children. If you are providing alternative content that will be displayed, my view is that you should use whatever HTML elements are most appropriate for displaying the default content, since it is valid to do so.

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
   codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" 
   width="368" height="190" title="This is my flash movie">
   <param name="movie" value="myFlash.swf" />
   <param name="quality" value="high" />
   
   <object data="myImageName.jpg" type="image/jpeg">
     Some text 
   </object>
</object>

Listing 2: Example of code for an <object> element embedding a .swf file. I’ve added a nested image object for browsers not supporting flash (think iPhone!), and some default text if images are not displayed or found.

The <object> element

<object> elements can be nested inside a parent <object> element to provide the browser with alternative content to present if the browser is unable to display the media included by the outermost parent <object>. The browser walks thru the nested <object> media until it finds a media type it can render. If a browser is unable to render the media type of the parent object, the browser will try to render the next child <object> element until it finds an <object> with a datatype it is able to render. The search for the first renderable child will continue thru all the included object, and, if no renderable <objects> are found, the browser will display any HTML content, including images, that is the child of the inner-most <object> element.

For example, if you are displaying a Flash movie, but the user’s browser does not have the flash player installed, then you can present the user an image. However, if the user is using a tele-type reader, then you can serve the user text instead.

If the <object> element does not display properly, the content nested between the <object> and </object> tags will be executed. This allows allows you to have several nested object elements (one for each browser, depending on browser media support), and default text for some browsers if the content is not found or if the media is not supported.

Note: When the browser supports the media type, but the file is not found, browsers differ on whether or not to show the nested content.

Examples of simple <object> elements in action

<object data="real_file.htm" type="text/html" width="300" height="200">
  <p>The link to <a href="missingfile.htm">a real page</a> will 
  not show in browsers,since browsers can render html</p>
</object>

EXAMPLE 1: Since the HTML data file DOES exist, the HTML file linked to with the data attribute will display. Browsers include the html file object in an iframe like display — in this case a 200 x 300px iframe since height and width were declared.

<object data="fake_file.htm" type="text/html" width="300" height="200">
  <p>The link to <a href="missingfile.htm">a missing page</a> will 
  show in some browsers, and not in others </p>
</object>

EXAMPLE 2: Since the HTML data file does NOT exist, the above will display differently in different browsers. For example, IE6 provides an empty iFrame like 200px by 300px space, Safari displays the paragraph, and Firefox displays nothing.

<object data="real_pdf.pdf" type="application/pdf" width="300" height="200">
  <p>The link to <a href="real_pdf.pdf>a real pdf file</a> will 
  show in some browsers. Others will display the Adobe Acrobat application 
  within and iframe</p>
</object>

EXAMPLE 3: Since the pdf file DOES exist, the HTML file linked to with the data attribute will display IF the browser supports displaying PDF files within a browser window. However, if the user’s browser does not support in-browser displays of Adobe Acrobat, the paragraph with the link to the pdf file will be displayed.

<object data="myMusicFile.mpeg" type="application/mpeg">
     <object data="missingImage.jpg" type="image/jpeg">
        My Text Replacement 
     </object>
</object>

Listing 4: If you have Quicktime, or some other audio format plugin supported by your browser, the music file will be displayed. If there is no media player, the browser will display the JPG instead of MPEG. However, in our example, the image doesn’t exist. Firefox and Safari correctly display the replacement text. However, IE6 tries to display the missing image.

Note that in example four, the image is included as an <object> instead of <img> because I wanted to display the text ONLY if the image did not load: I didn’t want to display both. Browsers will consider the <img> element as part of the data to be displayed if the user agent can not render the data in the outer object element. Since the <object> element does not support the alt attribute, a better way of coding the contents of listing 2 would be:

<object data="myMusicFile.mpeg" type="application/mpeg">
     <img src="myImageName.jpg" alt="My Text Replacement" /> 

</object>

This is more appropriate since you can include an alt attribute with the image. If a user agent does not render images, the text provided in the alt attribute will be displayed, which was what was intended in Listing 2.

Attributes of the <object> element

In addition to the core attributes and internationalization attributes, the <object> element accepts the following attributes:

  • declare

    The declare attribute, when included, states that the object should only be declared, not created or instantiated until needed. The declare attribute only takes one value: declare="declare".

  • classid

    The classid attribute defines a class ID value as set in the Windows Registry or a URL. Used to specify the location of the object’s implementation, the URL syntax depends upon the object’s type. The value can be either a traditional address or an apparently incomprehensible string of letters and digits that are actually the letters C-L-S-I-D, followed by a colon, space and the object ID, such as “CLSID: 99B42120-6EC7-11CF-A6C7-00AA00A47DD2”, for an ActiveX control. Classid is used in conjunction with or as an alternative to the data attribute. Unless you can figure out the Registry of classid’s, get the correct classid value from the supplier of the ActiveX control. For example, for .swf files, the classid value is generated by Flash when the developer publishes the .swf and associated .html file from the .fla file. Or, when using Dreamweaver to inset media, Dreamweaver automatically includes the correct classid value..

  • codebase

    This codebase attribute contains the URL to use as a relative base for the URL specified by the classid attribute. In Listing 2 above, the URL of the codebase points to the codebase for the flash player or plug in. Note that the URL for the SWF file is included in the child parameter and NOT in the <object> element.

  • data

    Another URL, the data attribute contains the location of the data required by an object. This should be either a relative or absolute path the your file.

  • type

    This type attribute specifies the content-type, or MIME type, for the object’s data. This is different from the codetype (below), which is the MIME type of the object and not of the data it uses.

  • codetype

    This attribute specifies an object’s content-type, or MIME type. This defines the MIME type of the object, not the the data the object may use, as defined in the data attribute.

  • archive

    This archive attribute contains an absolute or relative URL, or space separated list of URLs, for the location of archive files. An archive file is generally used to contain multiple object files to improve the ability to access the object improving perceived download time.

  • standby

    If you want to define the text displayed while the object is loading include the standby attribute with the text message to be displayed as the attribute value.

  • height

    This height attribute specifies the height of the object in pixels or as a percentage of the enclosing window, depending on whether the percentage symbol is included. This value is overridden if the CSS defines a height for the object.

  • width

    This width attribute specifies the width of the object in pixels or as a percentage of the enclosing window, depending on whether the percentage sign is included in the attribute value. The CSS width property overrides the element attribute value when included.

  • usemap

    Objects can have hyperlinks associated with them through standard links using the <a> element, thru embedded linking mechanisms such as links in a flash movie, and also via image maps. The usemap attribute generally takes a fragment identifier referencing a map element somewhere else within the file of the image map to be used with the object as the value, but can also take an URL to a map in a separate file in browsers that support such behavior. If you include the usemap attribute, you should also include a <map> and the object will most likely be an image. An image map specifies active geometric regions of an included object and assigns a link to each region. Image maps are covered in part 10 of this series.

  • name

    The name attribute is allowed, but is not required.

  • tabindex

    Along with <a>,<area>,<button><input>, <select> and <textarea>, the <object> element also supports the tabindex attribute.

The border, align, datafld, dataformats, datasrc, hspace and vspace attributes for the <object> element have all been deprecated in XHTML.

The <param> element

The <param> element is used to define special parameters used to control Shockwave and Flash SWF files, ActiveX controls, Netscape Navigator plug-ins, and Java applets. The <param> element can only be nested within a parent <object> or <applet> element. (Note that the <applet> element is not valid in XHTML strict). Parameters set attributes specific to different types of objects. For example, a Flash object can use a quality parameter <param name=”quality” value=”best”> for the object tag. If you are using Dreamweaver, you will find a Parameter dialog box in the Property inspector.

The <param> element is an empty element, so must be closed with a trailing slash. The name attribute is REQUIRED. The value attribute, while optional, should be included. The <param> element also accepts the id, valuetype, and type attributes.

Note: There is no widely accepted standard for identifying data files for ActiveX controls. See the documentation for the object you’re using for information on the parameters it requires.

Converting Flash to images

As web developers, we sometimes receive FLA, or Flash files, to include in our websites. Unfortunately, those Flash developers sometimes forget to include the original files used in creating the Flash Movie: files that would be really helpful in creating images used throughout the rest of the web site.

If you have the original FLA file, it is possible to export library items to create .png, .jpg and other useful files. While most tutorials here teach how to include images in your Flash file, in this tutorial we do the reverse: In this tutorial I’ll show you a simple method of exporting buttons, movie clips and graphics.

Steps to Exporting Images from Flash Files

Step 1: Open the FLA file that your Flash developer sent you.

Step 2: Open the Library of elements used in the FLA file. To open the Library press CTRL-L on Windows, or Apple+L on the Mac. Your library should look something similar to the Listing 1:

Flash Library

Listing 1: What a Flash library looks like when opened.

Step 3: Open a new Flash file by pressing CTRL-N, Apple-N or File > New then selecting Flash File from the options provided.

Step 4: You’ll note that when you open a new Flash file, the Library panel switches from the formerly active Flash file’s library to the Library for your new file, which is empty and untitled. However, you have access to the libraries of all the open Flash files. In the Library panel’s library name drop down menu, select the Flash file library that contains the library symbol you want to export.

Select the correct library from the drop down menu

Listing 2: Select the Flash file name of the Flash file opened in step from the "Library Name" drop down menu.

Step 5: Drag and drop the library symbol you would like to export by dragging and dropping the symbol from the library into your newly opened, currently untitled new Flash file.

Step 6: Export your movie into your selected file type. To export, select File > Export > Export Image.

Export your file

Listing 3: When you export a flash file as an image, you get the Export Image dialog window above.

Step 7: Enter a file name and select the location where you want the file saved. Also select the format for your exported file from the drop down menu in Listing 3.

Export Image Dialog Boxes

Listing 4: Sample dialog boxes that differ based on export file type selected.

Step 8: Depending on the file type you select, you will get a dialog box with options based on the file type. Select the options you want and select "OK"

What next?

That’s all there is to it! You now have a gif, jpeg, png, or even Illustrator, PCT, EPS, and, depending on your Flash version, possibly other file types.

This little trick has been useful to me when I don’t have the original files used in developing the Flash file, and for my own FLA files, when I don’t remember the file names of my compenents: this method is often quicker than searching my harddrive.

JavaScript Variable Scope

There are two variable scopes in JavaScript: local and global. Local variables exist only inside the function in which they were declared. Local scope means a variable can only be referenced from within that function in which it was declared. Global variables, on the other hand, once declared, exist throughout the script and their values can be accessed (and changed) from within any function or outside of a function. In other words, global scope means a variable can be referenced from anywhere within your site’s javascript.

There is a third type of scope called "static" or "closure". "Closures" are variables that are local to a function, but keep their values between function calls. Closures are an advanced javascript topic and will not be discussed in this article.

Let’s show 5 variables being declared, and discuss their scope

1.  <script type="text/javascript">
2.   
3.  var outsideFunction1 = "hello"; 
4.  outsideFunction2 = 42; 
5.   
6.  function myFunction(myParameter){
7.      var insideFunction1 = new Array();
8.      insideFunction2 = false;
9.  }
10.   
11. </script>

Listing 1: Example of local and global variable declaration

The first variable is on line 3: outsideFunction1. Even though this variable is declared with the var keyword, it is declared outside of any function, and therefore has global scope.

The second variable is on line 4: outsideFunction2. This variable is also declared outside of any function, and therefore has global scope.

The third variable is on line 6: myParameter. Function parameters always have local scope. Even if there were a global variable called myParameter, that global variable will maintain its value even if the value of myParameter was changed within the function.

The fourth variable is on line 7: insideFunction1. Because this variable is declared within a function with the var keyword, it also only has local scope. Similar to parameter variables, even if there were a global variable called insideFunction1, that global variable would maintain its value even if the value of insideFunction1 were changed within the function.

The fifth variable is on line 8: insideFunction2. This is really the reason that this article is needed: this is a global variable declared within a function, which is one of the most common causes of logic errors. Because the var keyword has been omitted, the insideFunction2 variable is global.

Local Variables

Variables initialized inside a function using the var keyword will have a local scope. If you initialize a variable inside a function without the var keyword, your variable will have a global scope. Parameters are local variables, as if the keyword var was included before the parameter. Local variables, including a parameters, can have the same name as a global variable.

var myName = "estelle";  // global
alertThisName("jonathan");
 
function alertThisName(myName){ // local
		alert(myName); // alerts "jonathan"
}
 
alert(myName); // alerts "estelle";

Listing 2: The variable myName is declared both globally outside of the function, and locally as the function parameter. Variables declared as function parameters have local scope. The myName variable on the first line is a global variable. The variable myName declared as a parameter of the function is a local variable only visible within the alertThisName function.

In this case, declaring a local variable with the same name as a global variable masks the global variable: all global variables in your script are accessible to this function EXCEPT the global myName variable.*

Note: In browsers, global variables that are masked by a function’s local variable with the same variable name are still accessible to the function by accessing the global variable thru it’s parent. In Listing 2, if you are in a browser, you could access the global myName variable from within the alertThisName function by using window.myName or top.myName.

var myCount = 7;  // global
doSomeMath();
 
function doSomeMath(){ // 
		var myCount = 7 * 7;
		alert(myCount); // alerts "49"
}
 
alert(myCount); // alerts "7";

Listing 3: In this example, the global and local variables both have the same name. Since the variable within the function was declared using the var keyword, the variable has local scope. Manipulating the value of the local value has no impact on the value of the global variable declared in the first line.
Once we exit the function, the local variable myCount no longer exists and recognition of the global variable’s existence is reinstated.

Similar to listing 2, in this case the local declaration of the myCount variable makes the global myCount variable inaccessible to this function. The function can access all global variables EXCEPT for the global myCount variable, unless you access the variable as noted in the tip above.

var myCount = 7;  // global
doSomeMath();
 
function doSomeMath(){ 
		myCount = 7 * 7;
		alert(myCount); // alerts "49"
}
 
alert(myCount); // alerts "49";

Listing 4: Since the variable within the function was declared WITHOUT using the var keyword, the variable has GLOBAL scope. The global variable declared in the first line and the variable used in the function both have the same name and are, indeed, the same global variable. In this example, manipulating the value of the global value within the function changed the value of the variable throughout the program.

function doSomeMath(){  
		myCount = 7 * 7;
		alert(myCount); // alerts "49"
}
 
alert(myCount); // throws an error: myCount is undefined

Listing 5: While the variable in the doSomeMath function would be a global variable, as the variable is declared in the function WITHOUT using the var keyword. Since the function is never called, the variable is never declared. Accessing the variable that doesn’t exist in the last line throws an error.

Rules to remember:

  1. Local variables inside a function can only be referenced from within the function in which the local variable was declared.
  2. All global variables can be referenced from within any function.
  3. All global variables can be referenced from outside any function.
  4. No local variables, declared with use of the var keyword, can be referenced from outside the function in which they were declared

Graded Browser Support

Do you really need to test all browsers? Is it even possible? Are you still testing Netscape 4.7 or IE 5? Which browsers are you supposed to test? Which can you ignore? Which browsers need to render your page pixel perfect, and which browsers should render the page, but if they break, you’re willing to live with that? And, for the browsers that you do plan on supporting, what operating system are you going to test them in? There’s Windows, Mac, Unix and Mobile to consider, but then there are various flavors of each: Windows XP, Windows Vista, Windows 2000, Windows ME, Windows 98, etc.

Graded Browser Support

Yahoo! Developer Network provides a list of what they call "grade-A browsers" which has become the defacto norm for browser support. Their article Graded Browser Support is a very clear articulation and formalisation of what many of us have been thinking about and implementing. If you haven’t been thinking about it, you should!

The general idea is that there are 3 classes or grades of web browser:

  • Grade-A: list of browsers we should thoroughly along with which operating system they should be tested on.
  • Grade-C: list of browsers that should be able to present the core functionality & content, but don’t need to be pixel perfect.
  • Grade-X: list of less common browsers and less common operating systems, for which Yahoo! (and you) need provide no testing and no support.

At the time of this writing, grade-A browsers include IE7, IE6, Safari 3.1, Firefox 2 and 3, and Opera 9.5. Grade A operating systems include Windows XP, Vista and 2000, and Mac 10.4 and 10.5.

At the time of this writing, neither Google Chrome or Internet Explorer 8 are included in the Grade A list. IE8 is not on the list since it is still in beta, and Chrome may not be on the list either because it is too new (the page is updated quarterly), it is too rare ( under 0.7% of the browser market share) or because it has a very similar rendering engine to Safari 3.1 (AppleWebKit/525.13 versus AppleWebKit/525.19).

I was surprised to find Windows 2000 still on the list of supported operating systems, and assume that will be downgraded soon. I am not copying the list in this article because whereas Graded Browser Support is updated quarterly, this page won’t be. So, bookmark Graded Browser Support to keep up to date with modern browsers and to stay abreast of what you should support and QA.

Which browser gets put into which grade depends on the market share. If you have a particular population that visits your website, your Grade-A browser may be different. For example, if you are building an Intranet for a company in which all employees are provided with a specific operating system, then that is the only operating system that should be in your grade A listing. Do take a look at your sites web statistics to determine if you have a large population of mobile visitors, old Mac users, unix users or some other population. Generally, the Graded Browser Support should work for 99% of audiences, but for your audience (or the audience you expect), it may differ.

Steps you can take

You will need to check your site in all grade-A browsers. However, there are some things you can do to make the whole process a lot easier:

  • Develop in Firefox with Firebug.
  • Write semantic code, separating content ((X)HTML) from presentation (CSS) from behavior (Javascript).
  • Write valid code, closing all of your elements
  • Add a space before the slash in self-closing, or empty, elements so very old browsers don’t choke: ex. <br />
  • Do NOT include the XML declaration at the top of your XHTML, as it breaks IE5 and sends IE6 into quirks mode.
  • In Javascript, check function capacity. Don’t browser sniff. Don’t use headers or proprietary features for browser detection.
  • In CSS, first create compliant, valid CSS code for compliant browsers before creating fixes for non-compliant browsers.

Staying relevant

Keep up to date on what browsers to support by visiting the Yahoo Graded Browser Support article on a quarterly basis (as that’s how often they update that article). Market Share is a great resources to see the current (and past) popularity of the various generally available browsers.

3-Column Layouts

Creating a three column layout with CSS: Part 1

Lets start with the XHTML. We start with a parent container, then include a header, content area and a footer, then add three columns to the content area. I will put "ipsum lorem" text in the examples that are linked from this page, but for the tutorial I will keep the content of our three columns, header and footer short.

<div id="parent">
     
  <div id="header">
		<p>HEADER</p>
  </div>
  
  <div id="contentarea"> 
    <div id="colA">
      <p>COLUMN A</p>
    </div>
    <div id="colB">  
      <p>COLUMN B</p>
    </div>
    <div id="colC">
      <p>COLUMN C</p>
    </div>
  </div>
  
  <div id="footer">
    <p>FOOTER</p>
  </div>
  
</div>

Just so we can see what is going on, let’s give them all borders and background colors, so we can tell the difference when we are doing this example. None of the following is part of what I want to teach you, but rather it makes the steps more legible and examples easier to understand.

#parent {
  border: 4px solid #ff0000;
  background-color: #222222;
}
#header  {
  border: 4px solid #ff9900;
  background-color: #444444;
  color #ffffff;
}
#contentarea {
  border: 4px solid #ffff00;
  background-color: #666666;
}  

#colA {
  border: 4px solid #66cc00;
  background-color: #888888;
}
#colB {
  border: 4px solid #3366ff;
  background-color: #aaaaaa;
}
#colC {
  border: 4px solid #663399;
  background-color: #cccccc;
}
#footer {
  border: 4px solid #ff33cc;
  background-color: #eeeeee;
}

<div>s are block level elements, so all this does is create blocks that go across the entire width of the page in normal flow. See our first example. Note: Adding borders to divs, as done above, affects their widths.

Introduction to creating columns

Normal flow is the way a document displays when there is no positioning or floating applied to it. The content will flow down the page, starting with the first element in your document and finishing with the last element in your document. The normal flow for a <div> is to take up the entire width of the page.

Instead of having the blocks of text one under the other, we want them to be next to each other, in "column" format. To create columns 2 things need to happen:

1) The sum of the widths of the three content divs, including the left and right borders, padding and margins of all three blocks of text, has to be less than the width of the container. We achieve this by setting the widths of the columns.

2) The blocks of text need can not appear in the normal flow, with divs above and below each other. Instead, then need to be "floated" next to each other.

Let’s add some CSS just as a preliminary example:

#colA, #colB, #colC {
  width: 30%;
  float: left;
}

I’ve set the width of the three columns to 30% instead of 33% because we have wide borders on the divs (remember: adding borders to divs as affects their widths). So the width is actually 30% + 4px left border + 4px right border. If you shrink the container width to below 240px, the right column will actually drop because the three columns width plus their borders is larger than the container because (30% * 240px + 8px total border) * 3 columns = 240px.

If you take a look at our second example, you’ll note that we have 3 columns, but the page is completely broken! Why? Because of float rules.

Floats: a primer

A float is a element that is laid out according to the normal flow, then taken out of the flow and shifted to the left (if floated left) or right (if floated right) as far as possible. When you float an inline element it becomes a block. Content can flow down the right side of a left-floated element and down the left side of a right-floated element, unless prohibited from doing so by the "clear" property, or because the width of a float is 100%. Floated elements will move to the left or right until their outer edge touches the containing block edge or the outer edge of another float. The top of a floated element will be at the same level as the float next to it, if there is enough room, or at the bottom of the preceding block if the element was originally inline. If there isn’t enough room on the current line for the floated box, it will move down, line by line, until a line has room for the float. (If two floats don’t appear to start on the same line, it is usually because the padding is different.)

Because a floated element is no longer in the normal flow of the document, non-positioned block boxes created before and after the float box flow vertically as if the float didn’t exist. If a parent or containing element only contains floats, the parent element will have no height, as if it were empty. This is what happened in our second example. Note that the #contentarea div (the yellow area) is only 8px high: the height of the top and bottom border.

A float can overlap other boxes in the normal flow. In our example, the three columns are taller than their parent and are overlapping the footer div.

One of the most important things to know about a float, and something that very few people know (and that I ask all potential job applicants) is that a floated element is at least as tall as the tallest floated element contained within it. So, let’s float the parent! but we need to give it a width, or it will shrink to be as narrow as possible. We need to get rid of the border, or our 100% will be 100% + 4px right border + 4px left border, which is more than 100%. Let’s make the background color different too, so it’s more visible. See the third example.

#contentarea { 
  float: left;
  width: 100%;
  border-width: 0;
  background-color: #ffff00;
}

There is a slight problem, which in the 100% width case wouldn’t really matter if we weren’t using such bright colors: note the top border of the footer is not showing. Why? Because the #contentarea has now been taken out of the normal flow. The text of the footer is appearing below the #contentarea because the content area width is 100%, so nothing can fit to the right of it, and therefore must be placed on the next line. Our page looks very different if we give the #contentarea a width of 50%: see the fourth example. The fourth example has similar issues to our second example, where the divs are going beyond the page.

Many instructors will advise to add a <br style="clear: both" /> equivalent here. I say we can do it much better! In the spirit of separating content from presentation, we can fix it via CSS without touching the HTML. Simply add the clear to the next element: the footer.

#footer { 
  clear: both;
}

Now, if you look at the fifth example, the footer falls completely below the content area, and we didn’t have to touch the HTML to add a <br>.

Now you know the basics of floats and the basics of using them to make a multiple column layout. In the rest of the series, I will show you how to make all three columns appear to have the same height, show you how to create columns differing widths, and point out some browser differences: how to avoid IE6 bugs and how to make various browsers render identically.

What we created was fairly ugly, but it worked. I will start from where we left off, but will remove the borders. I will continue to put "ipsum lorem" text in the examples that are linked from this page, but for the tutorial I will keep the content of our three columns, header and footer short. Notice the XHTML has NOT changed:

<div id="parent">
     
  <div id="header">
		<p>HEADER</p>
  </div>
  
  <div id="contentarea"> 
    <div id="colA">
      <p>COLUMN A</p>
    </div>
    <div id="colB">  
      <p>COLUMN B</p>
    </div>
    <div id="colC">
      <p>COLUMN C</p>
    </div>
  </div>
  
  <div id="footer">
    <p>FOOTER</p>
  </div>
  
</div>

We added colors to the divs so we could differentiate the columns from the footer from the header. I have changed the color of the #parent and #contentarea to make them more apparent for this tutorial:

#parent 
  background-color: #ff0000;
}
#header  {
  background-color: #444444;
}
#contentarea {
  background-color: #ffff00;
}  

#colA 
  background-color: #888888;
}
#colB {
  background-color: #aaaaaa;
}
#colC {
  background-color: #cccccc;
}
#footer {
  background-color: #eeeeee;
}

and finally, we added a few lines of CSS to make the columns work:

#colA, #colB, #colC {
  width: 30%;
  float: left;
}

#contentarea { 
  float: left;
  width: 100%;
}
#footer { 
  clear: both;
}

Recap of Part 1

What this bit of CSS did is gave the three columns widths that totaled less than the with of the parent element (the contentarea), floated the three "col" divs so they would appear as columns, and then floated the parent of the three columns so that the container of the columns would be at least as tall as the columns. Remember, because a floated element is no longer in the normal flow of the document, if a parent or containing element only contains floats, the parent element will have no height, as if it were empty. However, a floated element will always be at least as tall as it’s tallest floated child. So, by floating the #contentarea, the content area encompasses the three columns.

What we’re going to focus on in this tutorial:

Let’s take a look at the obvious issues in what we created. If you look at the current rendition of the columns, you will note the following:

  • The parent element (red) is showing thru above the content area, below the header.
  • The columns are all smushed to the left
  • The columns have no padding or margins
  • There is a lot of empty (yellow) space to the right, and jagged edges on the bottom.
  • The content, header, and footer are too tight: they also have no padding.

Making the page look nice

The first issue really has nothing to do with "column layout". It has to do with the default CSS of various browsers. Most browsers by default give margins to paragraph elements. If you are seeing the red #parent between the gray #header area and the yellow #contentarea, it is because the header paragraph has a bottom margin. That is why it is recommended to control your browser CSS defaults with a reset. Let’s control the header and footer and make them look header look nice.

#header {
	   padding: 20px;
}
#header p {
    font-style: italic;
    color: #ffffff;
    margin: 0;

}

#footer {
	   padding: 20px;
}
#footer p {
    text-align: center;
    margin: 0;

}

If you take a look at the page as it stands now, you’ll see it already looks better. So simple! Now lets address the columns.

Making the Columns look nice

What makes nice looking columns? Padding on all 4 sides. Padding between the columns. A middle columns being larger than the side columns. No ugly yellow. Columns being of equal height. hmmmm…. yup, we can do this.

To add padding to all 4 sides, we should simply be able to give padding to the parent container, but that won’t work! We declared the parent to be 100%; so adding padding would make to container wider than the header and footer. To make life easier for right now, let’s declare all widths in pixels instead of percentages.

#parent {
		width: 800px;
     margin: auto;
}
#contentarea {
		width: 760px;
		padding: 20px;
}

We declare an exact width for the parent of 800px. By declaring a margin of auto, the #parent will be centered.

We have added 20px of padding to the content area. That means 20px are added to the left and right (in addition to the top and bottom), so we have a total of 40px of padding between the left and right. 40px padding + 760px width = 800px.

We know we have 760px total for the three columns combined, so lets define their widths:

#colA {
	   width: 170px;
    margin-right: 40px;

}
#colB {

    width: 340px;
    margin-right: 40px;
}
#colC {
		width: 170px
}

If we do the math: 170px + 40px + 340px + 40px + 170px = 760px.
Note that we don’t need to add margin to the right of #col3, since we have the padding on the shell. Also, we use margin right instead of margin left because IE6 has a double-margin-float issue: when an item is floated to the left and and item has a margin-left that is greater than 0, IE6 doubles that width. Similarly, if an element is floated to the right, and the element has a margin-right that is greater than 0, IE6 will double that right margin. The page is actually looking really good in spite of the uneven columns, even in IE6. Let’s fix the uneven columns…

Creating Faux Columns using background images

We don’t want to declare a height on the columns since their heights will vary depending on the amount of content in the page. While there is no other way to ensure that the columns are the same height, we can make them appear to look like they are.

To create "faux columns", or appearance of columns with all the same height, we are going to add a background image to the #contentarea div that creates the appearance of columns for us.

#contentarea {
	   background-image: url(background.gif);
    background-repeat: repeat-y;
}

The image is simply a bar that contains a patch of color that is 210px wide on the left and on the right. Why 210px? The left padding is 20px. ColA is 170px wide. And, we want to cover half of the 40px margin between ColA and ColB with our column color: 20px +170px + 20px = 210px.

Background of faux columns

We’ve repeated this image vertically. To make the columns more interesting, I added a black 1px border. See the image above.

We need to remove the ugliness that we created to make this tutorial easier to follow, so we remove the background colors on colA, colB and colC.

#colA {
  background-color: transparent;
}
#colB {
  background-color: transparent;
}
#colC {
  background-color: transparent;
}

You can either overwrite the background color using the term "transparent" as above, or you can simply remove the CSS that we included earlier to create the background colors on those columns. Take a look at our final example. We have a presentable 3-column layout!

Practice on your own

You’ve learned the general techniques of doing a 3 columns layout. The same techniques can be used for 2-column or 4-columns layouts. Just remember that the columns, along with the added margins, need to be equal to or narrower than the parent holding those columns, accounting for any padding on that parent element.

If the total width of your columns is wider than the parent, your latter columns will drop below your first ones. If you have an item within a column that is wider than the column, like an image or too much padding, your column will drop. If a column drops, it is because your padding + margin + width of all your columns or their content was wider that the container, or because you forgot to float your columns.

The example in this tutorial uses specified widths. You are not required to use those exact widths. Try this tutorial using varying widths. Just remember to not exceed the width of the parent element, and, if you change number of columns or column widths, you will need to create a new "faux column" background to match your new layout.

This example also used padding and margins in a specific way to avoid IE6 bugs and common box model browser issues. I recommend using the padding on the parent and the margin on the columns in the opposite direction of the float to avoid any cross browser issues.

The layout we created may be all you need. But, what if they client says "I want the left nav on the right and the right nav on the left!"? Did you can change the order of your columns without touching your HTML? There is no re-ordering of the columns in a three column layout that isn’t possible.

In this tutorial, we look at the CSS required to change the order of your columns in your CSS without touching your HTML. I will continue to put "ipsum lorem" text in the examples that are linked from this page, but for the tutorial I will keep the content of our three columns, header and footer short. Notice the HTML has NOT changed:

<div id="parent">
     
  <div id="header">
		<p>HEADER</p>
  </div>
  
  <div id="contentarea"> 
    <div id="colA">
      <p>COLUMN A</p>
    </div>
    <div id="colB">  
      <p>COLUMN B</p>
    </div>
    <div id="colC">
      <p>COLUMN C</p>
    </div>
  </div>
  
  <div id="footer">
    <p>FOOTER</p>
  </div>
  
</div>

Listing 1: The HTML used in our examples

#parent {
    background-color: #ff0000;
    width: 800px;
    margin: auto;
}
#header  {
    background-color: #444444;
    padding: 20px;
}
#header p {
    font-style: italic;
    color: #ffffff;
    margin:0 ;
}

#contentarea { 
    float: left;
    width: 760px;
    padding: 20px;
    background-image: url(background.gif);
    background-repeat: repeat-y;
}
#colA, #colB, #colC {
    float: left;
}
#colA {
    width: 170px;
    margin-right: 40px;
}
#colB {
    width: 340px;
    margin-right: 40px;
}
#colC {
    width: 170px;
}
#footer {
    background-color: #eeeeee;
    clear: both;
    padding: 20px;
}
#footer p {
    text-align: center;
    margin: 0;
}

Listing 2: The CSS we are starting off with, based on Part 2 of this series in our embedded style sheet.

Recap of Part 1 and Part 2

In part 1, we floated the three "col" divs so they would appear as columns, and then floated the parent of the three columns so that the container of the columns would be at least as tall as the columns. Remember:

Because a floated element is no longer in the normal flow of the document, if a parent or containing element only contains floats, the parent element will have no height, as if it were empty. However, a floated element will always be at least as tall as it’s tallest floated child.

So, by floating the #contentarea, the content area encompasses the three columns. These three columns were all floated to the left. We declared a width on the parent element, added padding, then used simple addition to determine how wide to make each column and how wide to make the right margins on the first two columns.

Warning: Avoid the double float margin bug! When a margin is applied to a floated box on the same side as the direction the box is floated and the floated box is the first one inside its containing box, the margin is doubled in IE6 and lower. In other words, if a element is floated left, and you have a left margin of 20px on that element, that element will appear to have a left margin of 40px in older versions of IE.

In part 2, we used basic math to take our floated columns from part 1 and turn it into a better looking fixed 3-column layout, including margins and padding. To make the columns appear to have the same height we created "faux columns" by adding a background image to the parent of the three columns. We also added a bit of padding to the header and footer to make them look better. But that’s pretty much it…

Changing the left to right and right to left

The best part about separating the 3 layers of content, presentation and behavior, separating XHTML, CSS and JavaScript, is that you can do major layout changes without touching the original code. We are going to change the order of the columns from Column A-B-C to Columns CBA. To do this we float right instead of left. We also have to change the margins from right to left to avoid the IE double float margin bug.

#colA, #colB, #colC {
    float: right;
}
#colA {
    width: 170px;
    margin-left: 40px;
}
#colB {
    width: 340px;
    margin-left: 40px;
}
#colC {
    width: 170px;
}

Listing 4: CSS rules in an embedded style sheet changing column visual order to C-B-A

That’s all there was to it in this example. Had our #colA and #colC not have been of the same widths, we might have to change either their widths or the background image.

Note that we could have floated column C to the left instead, and then we can omit the left margin on column B.

Remember: class names and ids should be based on function rather than styling. If we had named the columns "left column", "middle column" and "right column", this tutorial would be really confusing. CSS may change your layout, but it won’t change your content. When choosing class and id names, think of the purpose of the styling rather than the styling itself. Choose names that make the funtion of the element clear. When creating a new design, you’ll be able to easily identify the purpose of the styling.

Changing it around again…

Just for yucks-and-giggles, let’s move the columns around again – Columns B-C-A.

#colA {
    float: right;
    width: 170px;
    margin-left: 40px;
}
#colB {
    float: left;
    width: 340px;
}
#colC {
    float: right;
    width: 170px;
}

Listing 5: CSS rules in an embedded style sheet changing column visual order to B-C-A

We floated Column A to the right. Because it’s floated right and we will be floating another element in that direction, we gave it a left margin. We wanted Column B to be on the left, so we float it left. Because no other elements are going to be floated left, there is no need to add a right margin. Then we floated column C to the right. We could have floated column C to the left, and it would have still been in the middle. Had we done so, however, we would have had to put a left margin on column B, and we could have omitted the left margin on column A.

Are there any issues with the redesign? Yes. Column B is the widest, but is now on the left. The background image was created for the middle being the widest. We can either change the widths or change the background. You’ll want to change the background image! You don’t want a wide navigation column and a narrow content columns.

Background of faux columns

Listing 6: Background image with largest column on left

 #contentarea { 
    background-image: url(background2.gif);
}

Listing 7: CSS rule to change the background image (you can also overwrite your image name instead)

You’ll want to create a background image that has the largest column first. You can overwrite your original background image file name. But, since this is a tutorial, I have given the image a new name, and therefore had to update the CSS. Now it looks right.

What have we learned?

By touching only the CSS, and not touching the (X)HTML, we were able to completely change the layout order. Pretty cool. Just remember, in creating 3-column (or more or less), calculate your margins, paddings and widths. If you go over the width of the container, your last column will drop. If you include elements in a column that are wider than the column, unless you declare the overflow property, will increase the width of the column and may cause the column to drop. And, again, if your margins look off in IE6 (or lower), it could be the double margin bug.

Only include margins when necessary. If you omit the margin when not necessary, you get a little bit of leeway should you have an element that increases the size of one of your columns.

Will floating alone take care of everything? No!

What are we missing?

With 3 columns, there are six possible column orders. We can get 4 of the layouts with simple floating and positive margins, but when the first column in content order needs to be in the middle, we have to go into new territory.

A B C – A – float: left; B – float: left; C – float either way
A C B – A – float: left; B – float: right; C – float either way
B C A – A – float: right; B – float: left; C – float either way
C B A – A – float: right; B – float: right; C – float either way

However, there are no combinations that allow us to create the following layouts using our simple CSS.
B A C
C A B

For these combinations, because of the first column in the (X)HTML being in the middle, it would seem that you couldn’t simply float the columns. You actually can. The trick is negative margins:

#colA {
    float:left;
    margin-left:380px;
    width:170px;

}
#colB {
    float:left;
    margin-left:-550px;
    width:340px;
}
#colC { 
    float:right;
    width:170px;
}
 

Listing 8: CSS rules in an embedded style sheet changing column visual order to B-A-C

With negative margins, we are able to place the first column in the middle. We float the first column to the left, but we give it a left margin to enable us to put Column B on the left. Column B is 340px wide. We also want to ensure that we include the 40px margin between Column B and Column A: 340px + 40px = 380px.

This is where the double float margin bug comes into play. Because we are floating left and providing a margin left on the first floated element within a floated parent, IE6 doubles the left margin provided. So we need to include IE6 (and older) conditional CSS in which we halve the left margin:

#colA {
    margin-left: 190px;

}

Listing 9: CSS rules for IE6 and less for changing column visual order to B-A-C

We then want to push Column B all the way to the left (well, inside the parent’s padding). If we simply floated it with no margin, the column would land at 550px from the left padding: the width of Column A (170px) and the left margin on Column A (340px): 170px + 340px = 550px. To put the column in the correct location, we give Column B a negative margin: margin-left: -550px;. The CSS looks weird. It is. But, mathematically, it works.

Note that again with Column C, you can float either left or right, but if you float left you need to include a left margin of 40px, so floating right is simpler.

Practice on your own

You’ve learned the general techniques of rearranging columns in a 3 column layout. I purposely omitted 2 columns combinations. On your own, try creating the following:

  1. A C B
  2. C A B

CSS Reset

Resetting browser default CSS

Whenever I start a new site and begin a new CSS file or CSS file set for the site, my first step is to include CSS to reset the browser CSS defaults.

Different browsers have slightly different default rendering. The default values for margin, padding and line-height differ between browsers. Removing the inconsistent default styling for elements in various browsers creates an equal starting point and allows you to explicitly set your own default settings that are equal in (almost) all browsers. By starting with an equal playing (or presentation) field, your CSS will not only look similar in all browsers, but your CSS file size will be smaller, and the number of aspirin you need to take to complete your site will be reduced.

Code

Here is the code I generally use. I’ll explain it below:

/* CSS BROWSER RESET */

body, div, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ul, ol, li, 
pre, form, fieldset, legend, input, textarea, label,
blockquote, table, th, td {
		margin: 0;
		padding: 0;
		background-repeat: no-repeat; 
		font-family: Verdana, Arial, Helvetica, sans-serif; 
		font-size: 100%; 
		line-height: 1.4; 
		color: #333333; 
	}
a, span {
		background-repeat: no-repeat; 
		outline: none;	
}

table {
		border-collapse: collapse;
		border-spacing: 0;
	}

fieldset, img, abbr, acronym {
		border: none;
		text-decoration: none; 
	}

ol, ul {
		list-style: none;
	}
caption, th {
		text-align: left;
		font-weight: normal;
	}

q:before, q:after {
		content: '';
	}

input, textarea, select {
		font-family: inherit;
		font-size:inherit;
		font-weight:inherit;
	}


 /* declare your site defaults here */

In your conditionally commented CSS file for IE7 and less include the following:

input, textarea, select {
		font-size:99%;
	}

CSS explained

While you may not use all the elements listed, and you may want your defaults to be slightly different, the above CSS is a good starting point. You might as well include all these elements, because you never know if someone else coding the site, or a future developer, may use those elements.

The first call sets the margin and padding of all elements to none. You won’t have to declare margin and padding of 0 again in your CSS. I have seen style sheets with ‘margin: 0’ included over 100 times. By including this default CSS, you only have to declare margins when you are overwriting the new zero default. Also, you don’t have to remember to explicitly set the body padding and margins.

Different browsers also display h1-h6 differently. This CSS nullifies the browser default settings and makes them look like the rest of your code. This way you decide how you want to display your headings. Also, by declaring a font-size in percentages, we resolve the IE ems rendering issues.

There are some settings in the code above that are redundant or irrelevant and will have no impact, such as setting margins on inline elements. CSS does not penalize you for including properties that are not used. I include all the elements in the first line, even though some of the properties are not used on some of the elements.

The default value for background images is to have them repeat on both the X and Y axis. Generally, you don’t want background images to repeat. The CSS above sets the background-repeat to no-repeat.

Just remember to AVOID use the background shortcut. If you omit one of the elements of the shorthand (background-color,
background-image,
background-repeat,
background-attachment,
background-position) you may inadvertently reset one of the properties to the default.

The call includes several optional/changeable items. Feel free to reset the font-family, color and line-height to your own preferences.

With font-family, include default fonts in the initial CSS browser reset. By declaring the fonts in this way, you will save a lot of characters by not having to declare default fonts elsewhere in your CSS. For example, if you declare your <h1> on your contacts page to have a unique font, you simply have to write something similar to:

#contact h1 { font-family: Hacknslash;} 

If the user doesn’t have the "Hacknslash" font, then it will default to Verdana, Arial, Helvetica, sans-serif, since you declared that in your brower reset CSS.

I chose the grey of #333333 instead of #000000, because black on white can be hard on the eyes. This dark grey is less harsh. You can use whatever color your design requires.

Line height is also up to you. You’ll note that there is no measurement type such as em, px, pt or % included. You can use these measurements. Omitting the measurement sets a number that will be multiplied with the current font-size to set the distance between the lines, similar to declaring em or %.

Since links, spans, code and other in-line elements have no default margin and padding and inherit, I declare them seperately to not overburden the browser rendering engine. I’ve declared two elements in this case as I use a lot of background images in my links and spans and want to ensure that those background images don’t repeat. The outline: none; on the links removes the box you may see around links when the mouse is down.

Note that you should not use the global selector, *, because the browser may overwrite default styling that you want to keep, such as padding on buttons. Also, when the global selector is used, the browser than has to apply the style to every element, which is a heavy load for the browser.

Defaults bullets are removed from ordered and unordered lists. Bullets are placed in different locations in different browsers: Firefox vertically aligns the bullet to text bottom and Internet Explorer vertically aligns the bullet to text top. I like to not only control my bullets, but generally my <li>s are inline, have background images instead of bullets, or are otherwise styled.

The caption and table header declarations are included since browsers tend to center them, and tend to bold table headers. The quote declaration is included since Firefox, Opera and other compliant browsers add quotes to <q>, while Internet Explorer, up to IE7, doesn’t even understand the :before and :after pseudo-classes. (This is resolved in IE8).

Most of the rest of the CSS is self explanatory except perhaps the IE conditional comments portion. Browsers are notorious for rendering forms differently: the input, textarea, select font-size declaration tells IE7 and earlier to not enlarge fonts that are in form elements.

Remember to include your form elements in block level elements. For example, put <textarea> in a <p> element so that it inherits font-family correctly in Opera.

The last line, "declare your site defaults here", is a good spot to declare the other default fonts and colors for your site. If all your h1s are going to be a different color and font, then start with your general, non-classed declarations. Remember to include this Browser Reset CSS at the top of your CSS. In this way, you can use the cascade to declare your defaults without requiring classes. Otherwise, you would have to include additional specificity for things that really should be generally declared.

Other browser reset arguments

There is an argument to remove ALL the defaults, such as bolding of the <strong> element, italicizing of the <em> element, monospacing of the <code> element, etc. The argument is that you should start from scratch, and build up all your own CSS. Below are some additional statements you can consider including in your CSS browser reset:

address, caption, cite, code, dfn, em, strong, th, var { 
	    font-style:normal; 
	    font-weight:normal; 
	} 
	h1, h2, h3, h4, h5, h6 { 
	    font-weight:normal; 
	} 

sup {
		vertical-align: text-top;
	}

sub {
		vertical-align: text-bottom;
	}