POSTS FOR 2003

LIR And Bug Fixes for IE5/Win

Browsers1578 words8 minutes to read

Internet Explorer Sucks

Most real web designers already know this. Most who don’t are generally either amateurs or are way, way behind the times. You’d think that with all of the money, power, and research and development resources Microsoft has, that they could produce a web browser better than crap. Apparently I’m mistaken.

Langridge Image Replacement

I’ve been using the LIR technique for swapping out text in favor of images for a while now. While no image replacement technique is perfect, LIR is better than the alternatives (namely FIR). What I like about LIR is that is does not require any extra HTML “hooks” to pull it all off. I know that FIR requires additional <span> tags.

Now, here is some sample XHTML markup for your basic LIR method:

<h1 id="header"><a href="/">Skyzyx.com</a></h1>

Simple enough, right? We have a top-level heading (<h1>) that encloses a link (<a>). Got it? Cool.

Here would be the CSS used to swap out the text in favor of an image:

h1#header, h1#header a {
    display:block;
    margin:0px;
    padding: 0px;
    overflow: hidden;
    width:710px;
    height: 80px;
}

h1#header a {
    padding: 80px 0 0 0;
    background: transparent url("/img/skyzyxcom.gif") no-repeat top left;
    height: 0px !important;
    height /**/:80px;
}

Now, what’s going on here? Well, the first rule sets up the parameters for both the <h1> tag and the <a> tag. Shared properties require less space than writing the same things twice, obviously. The second rule is only for the <a> element nested inside the <h1> element.

Starting with the first rule, display:block; says that we want to make both tags block-level elements. Since <h1> already is, this really only effects <a>. Since you can’t apply width and height properties to inline elements, we need to set the inline <a> element to block-level.

Setting the margin and padding to zero allows us to keep the box exactly the same size as the width and height — no more, no less — which is what we want. Since there is no margin or padding (as well as no border), Internet Explorer’s faulty box model issue doesn’t apply… yet.

The next property is overflow:hidden;. This says that any content inside the box (being the <h1> and <a> elements) that stretches outside the confines of the width and height will be hidden. That’s good, as that’s exactly what we want. But there is a slight problem here, as we will get to in a few minutes.

Lastly, we specify the width and the height that we want for the replacement image. At this point, you can still see the text, but we’ll get to that in a minute. We have now established the properties that the <h1> and the <a> have in common. Once again, Internet Explorer’s faulty box model issue has not come into effect yet, but it will… and we’ll be ready.

In the second rule (repeated from above):

h1#header a {
    padding: 80px 0 0 0;
    background: transparent url("/img/skyzyxcom.gif") no-repeat top left;
    height: 0px !important;
    height /**/:80px;
}

The first thing we do is overwrite the original value for the padding property with a new value. Note that this entire second rule only effects the <a> element, and NOT the <h1> element.

Here’s the concept behind this method: The correct box model (properly implemented in Gecko-based browsers like Mozilla and Netscape 6/7, as well as Opera) says that if you give an element a certain width, then that will be the width of the “content”.

Padding is empty space inside the box. If padding is applied, it will constrict the amount of room inside the box, which is good for giving space between text and any borders that may be around the box.

Margin is empty space outside the box. If margin is applied, it pushes outside elements away from the box, which is good if you want an element to be a certain distance away from another element. As an example, the content of this page has 50 pixels of margin on the top as well as on the bottom. That’s why you can see the grid behind it.

Border is exactly that… a border around the width of the box. You can set a border of 1 pixel, 2 pixels, 3 pixels, 50 pixels, or whatever you want. This all takes up space, and this space is taken outside the box, but before the margin is applied.

Apparently, according to these sources, although the box is made up of the content width + the padding, the actual width only applies to the content itself. This doesn’t make much sense to me, but that’s just how it is anyways.

The problem with the Internet Explorer box model is that instead of having the widthall of that stuff (content+padding+border+margin) has to fit inside the width. Oh no! (By the way, when I say “width”, the same issue occurs with the “height”.)

The way that this method works is that we create a “box”, eliminate all height, apply padding to hold the box open (to push the content text down below the border of the box), use overflow to hide that text, and then set a background image to it. Simple really.

But as I always say, “one horrible CSS rendering bug deserves another” (well, I don’t really always say that, but that’s what we’re going to do here).

Back to our regularly scheduled program, next we set the padding-top property to the height that we want to end up with, while setting the other paddings to zero. This will be critical to pulling this off.

After that, we address the background property. Here, we’re combining several background rules at once. We want the background color to be transparent, we want the background image to display (don’t use quotes for this, as IE5/Mac will crash), set the background to not repeat, and have it begin in the top-left corner.

This next part is what brings it all together. Internet Explorer 5.x doesn’t properly implement !important, so when other browsers see the !important, they’ll not allow the next line to overwrite this line.

We want to set the height to zero. Why? Because setting it to zero means that everything inside of it will be hidden because of the overflow property we set earlier. And since we set padding inside it, the element is held open by this padding… which gives it plenty of room to show the background image.

The last part of this whole equation is the box model fix for Internet Explorer 5.x. In this example, we use height /**/:80px;. IE5.x doesn’t properly handle !important, so when it comes across this line, it re-adjusts itself. Since IE5.x needs everything to be within the width (or height in this case), this fixes it’s problem.

Internet Explorer 6.0 also doesn’t understand !important, but it does have a parsing bug that this last line utilizes, so that IE6 never even sees it. Pretty nifty, huh?

Next…

Now, I explained all of that so that this next part would make sense. This method can be used with any element. Normally it’ll be an h-something tag, but what if you wanted to use a <div> tag? Well, it’d work just fine, except in IE5/Mac. Ethan Marcotte has shown us how to fix this.

h1#header, h1#header a {
    display:block;
    margin:0px;
    padding: 0px;
    overflow: hidden;
    width:710px;
    height: 80px;
    clip:rect(0, 710px, 80px, 0);
}

h1#header a {
    padding: 80px 0 0 0;
    background: transparent url("/img/skyzyxcom.gif") no-repeat top left;
    height: 0px !important;
    height /**/:80px;
}

Repetitive to be sure, but it works just great. However, there’s still a slight problem with Internet Explorer. This is a quirk that I noticed just recently in Internet Explorer 6.0, and was able to verify as bugs in earlier versions of Internet Explorer. For whatever reason, tiny bits of the tops of the letters peek up higher than they’re supposed to.

After looking around for information, I came across a site that said to set a negative indent for the text inside the link. So that’s what I did.

h1#header, h1#header a {
    display:block;
    margin:0px;
    padding: 0px;
    overflow: hidden;
    width:710px;
    height: 80px;
    clip:rect(0, 710px, 80px, 0);
}

h1#header a {
    padding: 80px 0 0 0;
    background: transparent url("/img/skyzyxcom.gif") no-repeat top left;
    text-indent: -1000em;
    height: 0px !important;
    height /**/:80px;
}

It works! Great! Now I’m off to the ne— wait a minute. What happened to the image in Internet Explorer 5.0? Where’d it go? Oh no! So, I got rid of the text-indent property, and took a look again. The image was back. Apparently, the text-indent property also moves the background image in IE 5.0. 4.01 and 5.5 get it right, but 5.0 screws it up. Sheesh!

I spent a few more minutes working with it, and decided to try something. In the first rule, the one that included both the <h1> and the <a>, we set the following property: overflow:hidden;. And since the <a> is nested inside the <h1>, if the <a> element is taller than the <h1> element, then the extra height will be hidden! Sure enough, it worked.

After getting rid of the text-indent property, I added 10 pixels to the height of the <a> element. Here was the final chunk of CSS code:

h1#header, h1#header a {
    display:block;
    margin:0px;
    padding: 0px;
    overflow: hidden;
    width:710px;
    height: 80px;
    clip:rect(0, 710px, 80px, 0);
}

h1#header a {
    padding: 90px 0 0 0;
    background: transparent url("/img/skyzyxcom.gif") no-repeat top left;
    height: 0px !important;
    height /**/:90px;
}

Kids, don’t try this at home.

Ryan Parman

Ryan Parman is an experienced software engineer, open source evangelist, and passionate user advocate currently living in Seattle. He is the creator of and , and worked on DevOps and Security at . He is now bringing learning into the digital age as an Engineering Lead and Site Reliability Engineer at . Ryan's aptly-named blog, , is where he writes about ideas longer than .