IE6 doubled float margin bug

The IE6 doubled float margin bug is well-known, and yet it is somewhat more complex than is often assumed.

Warning: Hypotheses and conclusions made below are purely the result of analysing test cases, and are of course subject to change as new test cases appear.

Characterization of the bug in IE6

Suppose we have

  1. A descendent chain of block-level elements beginning with a hasLayout container L (axiom)
  2. and otherwise consisting of a further none or more (exhaustive)
  3. non-hasLayout (sufficient) descendent boxes, until we reach an element containing
  4. a float F (axiom)
  5. whose ‘display’ property has not been specified as ‘inline’ (necessary) and which has a
  6. non-negative (axiom)
  7. side margin M whose edge E is incident with F’s parent’s content area side edge (necessary) such that
  8. F and M are not, respectively, a right float and a left margin (necessary).

Then a “magic margin” of width equal to that of M is appended to M at E. L expands to contain not only F’s margin area (as is usual under the hasLayout model) but its magic margin area. However, this expansion takes place after calculating widths of non-hasLayout blocks in the descendant chain, which are thus rendered as if no magic margin existed.

In the simplest and best-known case, a single floated element appears to have its inside margin doubled unless it is given ‘display: inline’.

Test cases

Case A – hasLayout parent, float display is unspecified

Left float, left margin

Left float, both margins

Left float, right margin

Right float, left margin

Right float, both margins

Right float, right margin

Case B – hasLayout parent, float display is inline

Left float, left margin

Left float, both margins

Left float, right margin

Right float, left margin

Right float, both margins

Right float, right margin

Case C – non-hasLayout parent, hasLayout grandparent, float display is unspecified

Left float, left margin

Left float, both margins

Left float, right margin

Right float, left margin

Right float, both margins

Right float, right margin

Case D – non-hasLayout parent, hasLayout grandparent, float display is inline

Left float, left margin

Left float, both margins

Left float, right margin

Right float, left margin

Right float, both margins

Right float, right margin