The IE6 Survival Guide

July 13, 2009

Supporting IE6 as a web developer is kind of like being a doctor and having to administer a physical (“turn your head and cough”). It sucks, but it’s part of the job. One would be hard-pressed to find a developer anywhere that has anything good to say about old Internet Explorer 6. It’s slow, short on features, and just can’t handle the rich designs and layouts that have become commonplace on the internet today. Unfortunately, IE6 still commands a significant enough slice of the market that it must still be supported. The following is a collection of problems that I deal with on a regular basis. This is by no means a list to end all lists. If you have a bug that you know about that I failed to mention, please post it as a comment. I want this to simply cover as many IE6 problems as possible, even if I’m not the one to address it.

Getting Started

Before we get into the major bugs and how to fix them, there are a few preparatory things we should do that will help make our code a little less hairy.

The first thing is to create a separate stylesheet for IE6. While many fixes involve very little code (you’ll find yourself putting display: inline; on a lot of divs), its best to keep all your IE6-specific CSS in one place. To add a IE6 stylesheet, use IE conditional comments in the code, like this:



These comments can also be modified to address any version or sub-version of Internet Explorer version 5 and up. This can prove quite useful, as you will most likely find your IE6 hack breaks IE7 or IE8 (or that your sane, standards-compliant code breaks IE6, IE7, or IE8). Having at the very least a separate stylesheet for Internet Explorer, if not one for each version, will ensure that your IE fixes don’t get in the way of real browsers rendering your page.

The other thing we should get out of the way from the get-go is setting up a PNG fix. Internet Explorer 6 does not support alpha transparency in images such as PNG-24, so we have to use a hack to get around this. There are a bunch of free solutions out there that use Javascript such as this PNG fix from ntlworld.com or this PNG fix that uses jQuery. There is also a way to implement a PNG fix with CSS.

Bugs

IE6 has plenty of bugs. To touch on all of them would take way too long, so I’ll go into a few of the more common ones. If there are any fairly common or especially notorious bugs that you feel I failed to mention, please leave me a comment and let me know. For a massive list of every single known IE6 bug, have a look at this Huge List of IE6 Bugs (it’s a little old, but it lists a ton of bugs).

Double Margin

One of the most common and notorious IE6 bugs, this involves the margin being doubled on any floating block-level element. The margin is only doubled on the side of the element which it is floating, so left floating elements will have double the left margin and right floating elements will have double the right margin.

For example, something like this in a halfway decent browser:

100 px Margin Example

would look like this in IE6:

IE6 Double Margin Bug

Fortunately, this problem is solved quite easily. By simply adding

display: inline;

to the CSS, the bug is no more. For further reading on this bug, check out Floats, Margin, and IE.

Ghost Character

Another fantastic little doozy you might run into when developing for IE6 is something known as the “ghost character” or “ghost text” bug. This problem is typically triggered by having HTML comments between two floating divs. The result is characters from the first div appearing in the second div, like this:

ghost-text

Lucky for you, this is also an easy fix. There are a few ways to skin this cat, but the easiest in my opinion seems to be simply adding

display: inline;

to the style for the divs that are giving you problems. There are a couple of other ways to fix the ghost text bug as well. For more reading on the ghost text bug and how to fix it, take a look at Explorer 6 Duplicate Characters Bug or Repeated ‘phantom’ or ‘ghost’ text display error in Internet Explorer.

Expanding Box Fail

Leave it to IE6 to take what the W3C recommends and do the exact opposite. This bug occurs when there is a element with content that exceeds the element’s explicitly-defined width or height, such as a really long URL with no breaks or a big image. Most browsers will preserve the width/height of the div, and treat the excessive content as overflow. IE6, however, will expand the size of the element to match the area the content takes up. When a page’s layout depends on floating divs being a particular size, this can be quite the problem.

To grasp the idea of this bug a little better, let’s look at an example. I ran the following code in Firefox, then in IE6:

<div style="float:left;width:300px;">
<div style="float:left;width:100px;background-color:#1111dd;padding:0;margin:0;">http://superlongurlthatwillbreakie6forsure.com</div>
<div style="float:left;width:200px;background-color:#11dd11;padding:0;margin:0;">Here is where the rest of the content would go</div>
</div>

This is what the code looked like in Firefox:

expanding-box-firefox

The URL in the blue div is longer than the fixed width of the div, and is treated as overflow. The layout is preserved. Now let’s take a look at what IE6 did to it:

expanding-box-ie

IE6 expands the width of the div to accomodate the content (despite me explicitly telling it NOT TO). This of course causes a float wrap, which breaks the layout.

The solution to this is a couple of lines of CSS:

overflow: hidden;
word-wrap: break-word;

The word-wrap property will cause any text content to wrap based on the width of the containing element even if there are no breaks. The overflow property will cause any other content such as images to be hidden past the width or height of the containing element. For more info about this bug, check out Internet Explorer 6 and the Expanding Box Problem.

Hacking CSS Support

CSS support in IE6 is a whole other beast. IE6 has very minimal CSS2.1 support, which means selectors you’ve come to know and love such as the > (parent > child) selector, :focus pseudo-class, and the [attr] selectors will not work. It also means that declarations such as min/max height/width and the :hover pseudo-class on anything but tags also will not work. With CSS3 around the corner and CSS2.1 practices being used more frequently, this is an increasingly frustrating problem. There are ways (mostly using Javascript) to emulate some of these properties in IE6. I’ll touch on a few and most likely edit later, but I encourage anyone that knows of any good ways to implement CSS2.1 in IE6 to leave a comment and let me know. For a more detailed list of CSS browser compatibilty, check out Quirksmode’s CSS Browser Compatibility Chart.

Min/Max Height/Width

The easiest way to achieve this in IE6 is to use Internet Explorer’s expression CSS declaration. Expression allows you to execute Javascript inside a CSS document. The only down side to using this method is that it will not work if Javascript is disabled (but let’s be honest, if you’re using IE6 and you have Javascript disabled, you’re pretty much S.O.L.).

For example, to emulate a min-width of 200px on an element in IE6, use something like this:

#some-div {
width: expression(  document.body.clientWidth < 200 ? "200px" : "auto" );
}

This is saying if the document window is smaller than 200 pixels, set the width to 200 pixels, otherwise just go with auto. Luckily, since we’re only worrying about one browser, clientWidth will work just fine for getting the window size. If you wanted to implement max-width instead of min-width on the above code, simply change the greater-than sign to a less-than sign. Emulating min-height and max-height involves similar code:

#some-div {
height: expression( this.scrollHeight < 200 ?  "200px" : "auto" );
}

Credit to this idea goes to Perishable Press. There is also another way to Implement Min-Width in IE6, but I find expression to be a little easier.

:hover On Tags Only

I find this becoming more and more of a problem as I begin to make pages that have more interactive elements. I may build a div that I want to slide open to reveal a form. This isn’t a link, but it would be nice to change the cursor to let the user know that it’s something that will react if they click it. Of course, in more modern browsers this can be accomplished with one line of CSS, but IE6 requires a little more finesse. There are a number of ways to do it, but I find the easiest way is to use jQuery (or your Javascript library/code of choice), like so:

$(‘#some-div’).hover( function() { $(this).css(“cursor”, “pointer”); } );

Again, there are a number of ways to do this, such as Using Prototype to Mimic the :hover Pseudo Class in IE6 or this Pseudo-Class Fix for Internet Explorer.

That’s All (for now)

Hopefully this has saved you a little time or prevented a headache or two. Again, I encourage any contributions you might have to this. Diggs and Stumbles are very much appreciated, and if you really liked this, you can follow me on Twitter at @jimdanko


Part of what makes jQuery so great is not only does the core functionality make life easier, but the extensibility of the library has opened the door to countless plugins that also make life easier. I use jQuery at my job just about on a daily basis (I’ll admit, I’m a bit of a jQuery junkie) and have used many different plugins. The following is a list of my top five favorites that I keep coming back to again and again.

Superfish

Odds are, if you’re building a web site, that site is going to have some sort of navigation. While there are many plugins for jQuery that are specific to menu functionality, I find Superfish to be my favorite for a number of reasons. First, the actual jQuery code that goes into implementing it is extremely minimal (as is the case with many plugins):

$(document).ready( function() {
$('#menu').superfish();
});

Where “menu” is the id of the unordered list of menu options. The markup for Superfish is also very unobtrusive. The only markup that needs to be added is class=”sf-menu” to the ul tag. Markup for a Superfish menu would look like the following:

<ul id="menu" class="sf-menu">
  • Menu Item 1
  • Menu Item 2
  • Menu Item 3
    • Menu Item 3 - Sub 1
    • Menu Item 3 - Sub 2
    • 
      
      
      
    • Menu Item 4
    • 
      

      Superfish is also pretty customizable if you choose to do that. The default alignment is horizontally, but it also offers options for both vertical alignment and a nav-bar alignment that displays sub-menu items in a small bar that spans the entire width of the menu, instead of a pre-defined area like the default styling does. To change the orientation of the menu, simply add a class of “sf-vertical” or “sf-navbar” to the ul tag along with the “sf-menu” class (class=”sf-menu sf-vertical”) and include an additional stylesheet.

      With its quick implementation and ease of customization, Superfish is an excellent choice for a menu plugin. For more documentation about how to further customize, and to download the source code along with examples,

      Visit the Superfish site

      jqModal

      There are a ton of modal window plugins for jQuery and I have yet to find one that is bad by any means, but I happen to prefer jqModal over the rest. I’m not going to rip on any other modal plugins or scold you for using a particular one over another. This is simply why I like this particular plugin, and I do not care to wax intellectual with anyone over which is the best one out there.

      I like jqModal because it is very bare-bones. All it gives you is a grayed-out window with a blank canvas and leaves the rest up to you, which I think makes it quite an all-purpose plugin. The code for it is very simple as well. To initialize a particular element as a jqModal window, use the following code:

      $(document).ready( function() {
      $('#modal-window').jqm();
      });

      Then in the markup, have something like this:

      The next step is to add a trigger for the modal. This is also really easy. While jqModal offers a few ways to add a trigger, I find the best way is to add it inside of a click function bound to the element you want to trigger the modal. For example:

      $(' #modal-open').click( function() {
      $('#modal-window').jqmShow();
      });

      Then in your markup have an element like this:

      View Lightbox Window

      By default, clicking the gray area outside the modal window will trigger the close event. However, it’s probably not a bad idea to have an element inside your modal window to close it. To do that, the jQuery code and HTML markup look very much like the code to open the window:

      $(‘#modal-close’).click( function() {

      $(“#modal-window’).jqmHide();

      });

      And the markup looks like:

      Close this window

      That is about all you need to know to get started with jqModal. It’s very customizable. The accompanying stylesheet is very small and is easy to build upon, and the jQuery code allows you to use it in a number of different ways. To learn more about jqModal and download the source code,

      Visit the jqModal website

      jQuery Bookmark

      Social bookmarking is creeping on to more and more sites. The company I work for deals primarily with online marketing for consumer brands, and I have found myself more and more coding “Add to Facebook” or “Tweet This” functionality. As with just about anything I find myself doing over and over, the need for a stable, reusable module soon became high priority. However, I recently discovered and had a chance to play around with the Bookmark plugin, and I will definitely implement it in the next project that calls for any sort of social bookmarking. Not only is the code fairly simple (like most of my favorite plugins), but it comes with built-in functionality for a ton of sites (many of which I haven’t even heard of). The most basic implementation looks like this:

      $(document).ready( function() {
      $('#bookmarks').bookmark();
      });

      This will display a bookmark box with every single site that is built in to the plugin. However, since you may not want that, there is also a way to specify the sites that should be included:

      $(‘#bookmarks’).bookmark({sites: “facebook”, “digg”, “delicious”});

      In addition, you can also add your own sites:

      //add a new site
      //parameters: (id, display name, icon url, site url)
      //id:  string that will be used to reference the site in the function ('digg', 'facebook', etc)
      //display name: text that will be displayed on the page
      //icon url: path to the icon to be used
      //site url: path to the site being added
      $.bookmark.addSite('myexamplesite', 'My Example Site', 'myexamplesite.png', 'http://www.myexamplesite.com?url={u}&title={t}');

      There is a ton of other stuff you can do with this plugin. If you’re interested,

      Visit the site and download the source code

      DataTables

      This is by far the coolest jQuery plugin I have come across. The sheer amount of stuff this bad boy can do is mind-blowing. Simply by calling the initialization function with the default settings like so:

      $(document).ready( function() {
      $('#tabular-data').dataTable();
      });

      you will be amazed by how much you can now do with that table of data. The only requrements for the markup in order for this to work are that the table must include the

      and

      tags. By simply doing this, you table will include functionality to search your entries, display a given number of entries, pagination, and will also add classes to alternating rows to allow you to add zebra styles to your table. Keep in mind this is all with the default configuration. Pretty cool, huh? If you add class=”sorting” to particular

      element, you can also sort the table by that particular column. There is an unbelievable amount of customization that can occur with this plugin. Rather than explain it all, I suggest you visit the official site and read the documentation yourself. Again, this is definitely my favorite out of this list.

      DataTables.net

      jQuery UI

      Ok, so I admit, this last one may be a bit of a cop-out, but I really felt it necessary to put on here. jQuery UI provides built-in functionality for so many things that so many people have wasted so much time building themselves. Custom dialog boxes, draggable elements, date pickers, tabs, and progress bars just to name a few. Adding jQuery UI elements to your page can really make it function like a desktop application. Like the previous plugin, there is simply way too much stuff that it can do to explain here. I would definitely recommend checking out the documentation though and using it.

      jQuery UI

      So there you have it, a list of my five favorite plugins that have saved me a lot of time and headaches, and continue to do so. Hopefully you find these as useful as I do. I encourage you to check out the repository of jQuery plugins on the official jQuery site, as you may find that what you are trying to do may already be built and ready to go.


      I had an issue with an application I was writing recently that positions a lightbox based on the height and with of the image inside it. I was using Javascript to get the height and width of the image, then adjust the CSS on the lightbox accordingly before displaying it. However, Internet Explorer kept returning 0 for the height and width image, causing the lightbox to display improperly.

      The Problem:
      Part of the application I was writing involved displaying a table with a list of image information. When a row of the table was clicked, the image itself is displayed in a lightbox positioned in the center of the screen based on the height and width of the image. I was using jQuery and the jqModal plugin to do this. I set the click event of the table row to change the ‘src’ attribute on the image tag inside the lightbox, and binded a load event to the image tag inside the lightbox that repositioned the lightbox then displayed it. That way, I was sure that the code to grab the dimensions of the image wouldn’t execute until the image was loaded. At least, that’s what I thought. For some reason, Internet Explorer was not getting the dimensions of the image, causing the upper-left corner of the lightbox to always be in the middle of the screen, despite the size of the image.

      I discovered that the source of the problem was that because the lightbox was set to “display: none” when the src attribute was changed, the image wasn’t actually being loaded despite triggering the load event. Internet Explorer does not load images unless they are actually being displayed. Because of this, I kept getting 0 as the height and width of the image.

      The Solution:
      It turns out that the images will load properly if the containing element is set to “visibility: hidden”. However, since jQuery and the plugin I was using hides elements by setting them to “display: none” by default, I merely implemented a workaround for IE which looks something like this:


      if ( navigator.appName == "Microsoft Internet Explorer" ) {

      $('#lightbox-image-container').css('visibility', 'hidden');

      $('#lightbox-image-container').css('display', 'block');

      }

      var image = document.getElementById("lightbox-image");

      var imgWidth = image.width;

      var imgHeight = image.height;

      if ( navigator.appname == "Microsoft Internet Explorer" ) {

      $('#lightbox-image-container').css('display', 'none');

      $('#lightbox-image-container').css('visibility', 'visible');

      }

      Note I used document.getElememtById to reference the image rather than using the jQuery width and height methods because the former is more compatible cross-browser.