IE hasLayout and the return of the Guillotine bug

One of the most notorious of Internet Explorers' bugs is the Guillotine Bug commonly seen with IE6. Chris Wilson was proud to announce on the Microsoft Blog in 2005 that this bug among many other bugs affecting IE6 were to be fixed with IE7. Well it's interesting to know truly what has been fixed or left unfixed, being a bug or non standard compliant behavior. IE7 like IE6 before it, still auto contains all floats inside a container with hasLayout. It is this behavior which is the cause of the original Guillotine Bug seen with IE6 and since this behavior is still present in IE7, it's likely that there are still bugs lurking in the shadows.

Update (5th May 2008): IE8 which is now in development does not have this bug.

Disclosure (20th September 2009): This variation of the Guillotine Bug was found by me on Douglas Bowman's website Stopdesign in April 2007. This site now has a new design.

Let me demonstrate a different variant of the Guillotine Bug that works in IE7 and earlier versions of IE as well. Please hover over the Guillotine Link in the following example.

Example 1: IE Guillotine Bug with two or more floats

Hover over this Guillotine Link in your choice of IE
When you have finished just hover the Reset Link

Floats contained by elements with hasLayout

Some of Internet Explorer's bugs in implementing CSS specifications is due to effects of hasLayout on elements that contain floats. When hasLayout is set to true for these elements, they becomes a rectangular shape and the consequence of which is the element with layout auto contains its contents. This is clearly seen in the above example.

Screenshot in Firefox

Firefox Screenshot

Screenshot in Internet Explorer 7

IE7 Screenshot (before)

Screenshot in Internet Explorer 7

IE7 Screenshot (after)

Screenshot in Internet Explorer 6

IE6 Screenshot (after)

Stirring the Pot

The magic ingredients that invoke the basic Guillotine Bug in IE6 are:

  1. A container element with hasLayout.
    Note: When the original Guillotine Bug was demoed, the MS propriety property hasLayout was largely unknown; the caused as understood then was a container with a dimension.
  2. A float element inside the container that is not cleared.
  3. Links inside the container in non-floated content after the float.
  4. a:hover style rules for those links that change certain properties.

Removing ingredient three from the above conditions we add to the mix some more magic ingredients to invoke another IE Guillotine Bug, they are:

  1. A second or later float element either floating left or right inside the container that is not cleared. The second or later float must be shorter than any preceding float or floats.
  2. A anchor (trigger) link inside the container in non-floated content coming before all floats. This link must be contained by particular elements inside the container or have certain content between the trigger link itself and the float.
  3. Since IE7 supports hover on any element, it can also now be :hover style rules for any element that change certain properties.

The basic HTML and CSS that invokes the guillotine is below.

  1. <div class="ancestor"> ..
  2. .. <a>Guillotine Link</a> ..
  3. <div class="descendant1"> .. </div>
  4. <div class="descendant2"> .. </div>
  5. </div>
  1. .ancestor {width:350px;} /* hasLayout = true */
  2. a:hover {background:#F00;} /* transition trigger */
  3. .descendant1 {float:left;}
  4. .descendant2 {float:left;}

Example 2a: IE Guillotine Bug with width (float covers content)

Guillotine Link
Static div

Float 1

Reset Link

When the Guillotine
is triggered in IE6,
this content is hidden
Float 2

Reset Link

When the Guillotine is triggered in IE7 this static element jumps up and is positioned below the gold container which now only auto contains the second float, but the text in this static element is not displaced by the first float but is covered by it

The above example and the next two examples have a blue 'e' on a div containing the wrapper. This is to show how a background image could be covered.

Example 2b: IE Guillotine Bug with width (float covers content)

Unlike the previous example, this example will appear the same in both IE7 and IE6. This is because the first float (the guillotine) has {position:relative;}. Thanks to Bruno Fassino for making me aware of this with IE6.

Guillotine Link
Static div

Float 1

Reset

This float has
{position:relative;}
IE7 & IE6 shows
the same
Float 2

Reset

When the Guillotine is triggered in IE7 and IE6 this static element jumps up and is positioned below the gold container which now only auto contains the second float, but the text in this static element is not displaced by the first float but is covered by it

Example 2c: IE Guillotine Bug with width (part of float is covered)

Guillotine Link
Static div

Float 1

Reset

When the Guillotine
is triggered in IE7 &
IE6 this content is
hidden
Float 2

Reset

This element now has hasLayout so when the Guillotine is triggered in IE7 this static element jumps up and covers the lower part of the first float. IE6 will show the same as with example 1a

New hasLayout triggers, new variants of bugs

For the property 'Overflow' the values 'hidden', 'scroll' and 'auto' are some of the new hasLayout triggers in IE7, and ironically, it is this property and values which are now catching on as one way to allow containers to contain floats in good browsers and mimic the IE auto containment of float bug if a container has hasLayout.

The grandest ironically of all is that to make IE7 more standard compliant the IE team decided to make these 'Overflow' values trigger hasLayout. Now IE7 really shows bizaar examples of the guillotine bug. This is not the way to support standards.

Example 3a: IE Guillotine Bug with overflow hidden

Guillotine Link
Static div

Float 1

Reset

When the Guillotine
is triggered in IE
this content is hidden
Float 2

Reset

When the Guillotine is triggered in IE7 and IE6 this static element jumps up and is positioned below the gold container which now only auto contains the second float

The above example and the following examples have a blue 'e' on the gold container. This is to show how a background image could be covered.

Example 3b: IE Guillotine Bug with overflow auto

Guillotine Link
Static div

Float 1

Reset

When the Guillotine
is triggered in IE
this content is hidden
Float 2

Reset

When the Guillotine is triggered in IE7 and IE6 this static element jumps up and is positioned below the gold container which now only auto contains the second float

Please note that there is two stages in execution when auto is used. Firstly when the link is hovered over, room is created inside the container for a coming scroll bar and secondly when the link is hovered off this triggers the guillotine. Since such amazing things can happen, if the two contained floats are just wide enough to just fit inside the container then only the first stage of execution happens when the link is hovered over. Please try the next example which shows the second float dropping below the first float. The reset links will not work. The only way to correct it is to refresh the page.

Example 3c: IE Guillotine Bug with overflow auto

Guillotine Link
Static div

Float 1

Reset

See that 'e' to the right.
If you want to
release some
frustration
with it, then
guillotine it
Float 2

Reset

Example 3d: IE Guillotine Bug with overflow hidden

Guillotine Link
Static div

Float 1

Reset

This float has
{position:relative;}

so covers the
element below
Float 2

Reset

When the Guillotine is triggered in IE7 and IE6 this static element jumps up and is positioned below the gold container which now only auto contains the second float with has a negative bottom margin

Both the above example and the next example show the removal of the second float with negative bottom margin. This technique I first saw demonstrated by Gunlaug Sørtun which is demonstrated here.

Example 3e: IE Guillotine Bug with overflow auto

Guillotine Link
Static div

Float 1

Reset

When the Guillotine
in IE is triggered
both floats are hidden
Float 2

Reset

When the Guillotine is triggered in IE7 and IE6 this static element jumps up and is positioned below the gold container which now only auto contains the second float with has a negative bottom margin

Example 4a: IE Guillotine Bug with position absolute

Now that IE7 now supports offsetting both left and right together for absolutely positioned elements we have yet another way to evoke a guillotine. If a width is given the bug is not present but in IE6 this is a different story and when the guillotine is triggered the repositioned Ap. elements remains frozen (if this doesn't work, resize the viewpoint). This all corrects itself when the page is refreshed.

Ap. 1 and some content
Ap. 2 and some content
Guillotine Link
Static div
Float 1

Reset

Content

Content
Float 2

Reset

When the Guillotine is triggered in IE this element is covered by the Ap. elements

Example 4b: IE Guillotine Bug with position fixed

I guess you have been wondering about that example at the bottom left corner of the page. Try this, hover the heading above and then this paragraph. Wow, that something special! Also in IE6 there is hidden text for that browser to help explain why this example doesn't work in IE6 and what happens in IE7.

If you can read this text then you are using IE6 or an earlier version or if you are hearing this text then you are using a screen reader. This example does not work in IE6 or earlier since they do not support fixed positioning. In IE7, this example is fixed at the bottom left corner of the viewpoint and when the guillotine is triggered the yellow container drop out of the viewpoint to the level of the later float.
Static div
Static div

Example 5b: The original IE Guillotine Bug revisited

There is a way to circumvent any hack the IE development team used to stop the original bug in IE7. We just pull out another IE bug associated with hasLayout and floats and use that as a trigger.

Yes indeed..... it's possible to toggle on and off the fix that was applied to IE7 to stop this type of guillotine happening.

Float left

Content

More Content

More Content

Example 6: IE Guillotine Bug

The link that triggers the guillotine can just be enclosed by ancestor elements that don't have layout. In the example below are the <p> and <div> elements within the gold container with layout. The link that triggers the guillotine does not work if there is just alone a <p> or <div> element. Also there can be an element between the two floats. The example below has a dark green <div> element that does not have layout. The floats themselves can be enclosed by elements without layout.

Float left

Content

Content

Content

Content

Un-floated element

Reset Guillotine

Float right

Content

Content

Content

Float left

Example 7: The Tripple Guillotine

The right nestling of containers and floats can produce multiple guillotine to be present on one page. Hovering over the links marked 1, 2 and 3 will result in all guillotines being activated.

Guillotine C (3)

Guillotine A & B Link (2)

Reset

Guillotine B (1)

Reset

Float right (B)

Content

More Content

Float left

Float right

Float right (C)

Reset C

Clear right

Float right

The Fixes

  1. <div style="clear:both"><!-- --></div>
  2. <br style="clear:both" />

Example 1: IE Guillotine Bug fix with a clearing element

Hover over this Guillotine Link in your choice of IE
When you have finished just hover the Reset Link

The basic HTML and CSS that fixes the guillotine is below.

  1. <div class="ancestor"> ..
  2. .. <a>Guillotine Link</a> ..
  3. <div class="descendant1"> .. </div>
  4. <div class="descendant2"> .. </div>
  5. <div class="clear"><!-- --></div>
  6. </div>
  1. .ancestor {width:350px;} /* hasLayout = true */
  2. a:hover {background:#F00;} /* transition trigger */
  3. .descendant1 {float:left;}
  4. .descendant2 {float:left;}
  5. .clear {clear:both;}

Example 1: IE Guillotine Bug fix with a hasLayout container around the trigger links

Hover over this Guillotine Link in your choice of IE
When you have finished just hover the Reset Link

The basic HTML and CSS that fixes the guillotine is below.

  1. <div class="ancestor"> ..
  2. <div class="haslayout"> ..
  3. .. <a>Guillotine Link</a> ..
  4. </div>
  5. <div class="descendant1"> .. </div>
  6. <div class="descendant2"> .. </div>
  7. </div>
  1. .ancestor {width:350px;} /* hasLayout = true */
  2. a:hover {background:#F00;} /* transition trigger */
  3. .descendant1 {float:left;}
  4. .descendant2 {float:left;}
  5. .haslayout {height:1%;}

Example 1: IE Guillotine Bug fix with a hasLayout container around the floats

Hover over this Guillotine Link in your choice of IE
When you have finished just hover the Reset Link

The basic HTML and CSS that fixes the guillotine is below.

  1. <div class="ancestor"> ..
  2. .. <a>Guillotine Link</a> ..
  3. <div class="haslayout"> ..
  4. <div class="descendant1"> .. </div>
  5. <div class="descendant2"> .. </div>
  6. </div>
  7. </div>
  1. .ancestor {width:350px;} /* hasLayout = true */
  2. a:hover {background:#F00;} /* transition trigger */
  3. .descendant1 {float:left;}
  4. .descendant2 {float:left;}
  5. .haslayout {height:1%;}

Conclusion

I Need to write a new conclusion since IE8 does not have this bug but we still have to deal with it in IE7 and earlier versions of that browser for the near future.

References and links

This article was created on the 30th of May, 2007 and last updated on the 5th of May, 2008.

Author: Alan Gresley