It's Movember. Movember is a yearly, world-wide fundraiser for research of men's health problems, such as prostate cancer and depression. Your donation will count, even if it's just $1. Click here to donate.
Use Bodhi Linux—It's awesome!

hasLayout.net

Share |

3px Gap Bug aka Text Jog Bug

Affected Versions

This bug affects: IE6

Symptoms

Elements next to a floated one either have a three pixel gap or drop below or keep shifting when several elements are floated.

Date of the Tutorial

Fri Jul 17 02:02:41 2009

Description

Here is a rather interesting bug. In IE elements with haslayout set to a true value act differently around floats. They don't want to go under the floats, they don't even want to touch floats, in fact, giving "layout" to an element is IE's way to contain floats. However, this bug shows itself in three different flavors. Let's take a look at the demos.

Demo

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
HTML Code:
<div id="container">
    <div id="bugger">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit.
    </div>
    <div id="victim">*cry*</div>
</div>

<div id="container2">
    <div id="bugger2">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit. 
    </div>
    <div id="victim2">*cry*</div>
</div>

<div id="container3">
    <div id="bugger3">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit. 
    </div>
    <div id="victim3">*cry*</div>
</div>
<div id="container4">
    <div id="bugger4">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit.
    </div>
    <div id="victim4">*cry*</div>
</div>
CSS Code:
#container,
#container2,
#container3,
#container4 {
    width: 500px;
    overflow: hidden; /* just containing floats */

}
    #bugger,
    #bugger2,
    #bugger3 {
        float: left;
        width: 300px;
        background: #65A5E1;
    }
    #bugger3 {
        background: none;
        border-right: 1px solid #000;
    }
    #victim {
        width: 200px;
        margin-left: 300px;
    }
    #victim2 {
        height: 1.5em; /* just to give "layout" */
        margin-left: 300px;
    }
    #bugger4 {
        float: right;
        width: 300px;
    }
    #victim4 {
        width: 200px;
        margin-right: 300px;
    }

Let's break each of these demos one by one. Let's start with the first one. We have three elements. Fixed width #container, inside of which are one floated element (#bugger) and another element (#victim) with left margin set to the width of #bugger. Even though you may not see this in professional code, since arguably there is little use for width in our second child element, #victim, it is this bit that makes the bug obvious. Without #victim { width: 200px; }, but haslayout still being true the bug will introduce itself as a simple three pixel gap between #victim and #bugger which can be seen in second demo (#container2). Finally, if element next to the floated one does not have "layout" the bug will be hardly noticable. Third demo (#container3) shows the effect. The text inside #victim3 is still offset by three pixels which indicates that the bug affects inline boxes generated by text, images and alike. This is how the bug got its another name "Text Jog Bug". The bug in the third demo (#container3) may not be that obvious. However, if instead of text we would have a 200 pixel wide image, it would go down and would look pretty much as what we see in the first demo (#container).

Take a look at the last demo (#contaier4). It is clearly seen that the bug is present even if we use float: right instead of float: left.

Solutions

Below are solutions for the above bug ordered by the solution type.

Solution (Conditional Comments Solutions)

Date of the Solution

Fri Jul 17 02:17:02 2009

Fixed Versions

all of the affected

Description

Despite the fact that the fix for this bug seems like a raw blow in the jaw, "give me this piece back", it is is quite effective.

Note that in all those demos the "gap" is exactly three pixels. That is what we are going to use to fix it with the solutions varying slightly depending on how the bug manifests itself.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
*cry*
HTML Code:
<div id="container">
    <div id="bugger">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit.
    </div>
    <div id="victim">*cry*</div>
</div>

<div id="container2">
    <div id="bugger2">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit. 
    </div>
    <div id="victim2">*cry*</div>
</div>

<div id="container3">
    <div id="bugger3">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit. 
    </div>
    <div id="victim3">*cry*</div>
</div>

<div id="container4">
    <div id="bugger4">
        Lorem ipsum dolor sit amet,
        consectetuer adipiscing elit.
    </div>
    <div id="victim4">*cry*</div>
</div>
CSS Code:
#container,
#container2,
#container3,
#container4 {
    width: 500px;
    overflow: hidden; /* just containing floats */
}
    #bugger,
    #bugger2,
    #bugger3 {
        float: left;
        width: 300px;
        background: #65A5E1;
    }
    #bugger3 {
        background: none;
        border-right: 1px solid #000;
    }
    #victim {
        width: 200px;
        margin-left: 300px;
    }
    #victim2 {
        height: 1.5em; /* just to give "layout" */
        margin-left: 300px;
    }
    #bugger4 {
        float: right;
        width: 300px;
    }
    #victim4 {
        width: 200px;
        margin-right: 300px;
    }
Conditional Comments:
    <!--[if lt IE 7]>
        <style type="text/css">
            #bugger,
            #bugger2,
            #bugger3 { margin-right: -3px; }
            
            #bugger4 { margin-left: -3px; }
            
            #victim,
            #victim2 { margin-left: 0; }
            
            #victim4 { margin-right: 0; }
        </style>
    <![endif]-->

All the code is the same as in our original demo with the exception of condcoms. The conditional match in condcom matches any IE version below 7 which is exactly the versions which 3px Gap Bug affects.

The solution involves applying a negative margin of three pixels to a floated element (#bugger element in our demos) on the side where the bug happens. Thus for the first three demos we have used margin-left. Since our last demo has value right for the float property on #bugger4 we have used the opposite, margin-right instead.

Note that it is not a magic number three. We have used value of -3px for margins in our demos only because their original value is zero. The value which should be passed to IE versions below 7 should be three pixels less than the original. Thus, if we would have used #bugger { margin-right: 30px } in our first demo, we would have used #bugger { margin-right: 27px } in the condcoms.

Now the second part of the fix. We need to zero out all the margins on #victim, #victim2 and #victim4. Why? Because of the way IE treats elements with "layout" around floats, thus in IE, due to "layout", the margins on #victim, #victim2 and #victim4 would start from the edge of the #bugger instead of going under it as it happens in sane browsers.

The margin on #victim3 is not set to zero because it does not have "layout" thus it does go under the float.

Comments

If you found materials on this site useful, please consider donating a few bucks to the author. Thank you.

Alternatively, purchase my books: