[CSS21] Clearance - the missing manual

It ends in a cliffhanger...

Why is clearing floats desirable?

There are various reasons.  The available space next to a float may be
rather too narrow for certain content to look pleasing when flowed
alongside.  Section headings often look better below the floats of
previous sections rather than alongside them.

So we need a mechanism for pushing the clearing element downwards?


Can we use increased top margin on the clearing element?

No, that would mean that if the top margin of the clearing element
collapses with the float's parent, then the float would move down too!

 <div style="float:left; width:100px; height:100px></div>
 <div style="clear:left; margin-top:50px">text</div>

What about introducing spacing below the clearing element's top margin?

No, that would stop its first child's top margin from collapsing.

 <div style="float:left; width:100px; height:100px></div>
 <div style="clear:left">
  <h2 style="margin-top:50px">text</h2>

So we have to prevent the clearing element from collapsing margins with
its parent?

Yes.  That's half of what clearance is; it's a margin collapsing
interrupt.  (The other half of it is about moving the clearing element
to the desired position.)

Shouldn't the clearing element still collapse margins with previous

No, that would mean that when we moved the clearing element to the
desired position, the previous siblings would move too!

So the clearing element can't collapse with any previous margin?

Exactly.  We interrupt margin collapsing immediately before the clearing

Does interrupting margin collapsing have side-effects?

Yes; in particular, the float can itself move upwards!

 <div style="float:left; width:100px; height:100px"></div>
 <div style="clear:left; margin-top:50px">text</div>

Heh, that's funny.  So what's the desired position to which we move the
clearing element?

So that its top border edge is the lower of:
 - below the float
 - where it was before margin collapsing was interrupted

The second consideration addresses the case where the float moves
upwards after interrupting margin collapsing.  It would be strange to
move the clearing element upwards!  Prior to clearing, it was as low
down as it was for good reason: sensible margin collapsing with
surrounding in-flow elements.

Why consider the top border edge and not the top margin lump edge?

That's just the way it is.  Bottom margin on the float can be used to
provide separation.

Simple! So what's the catch?

The presence of "self-collapsing" elements whose own top and bottom
margins collapse makes life difficult.

Why aren't self-collapsing elements discarded from the layout?

Even though they're invisible, they interact with other document
elements in the normal ways.  For example, their width establishes the
available space for floated children, and of course their vertical
margins affect the position of descendants and subsequent elements.  And
discarding them would be the cause of strange discontinuities: imagine
an inline element containing a block-level element containing a float;
the layout would change significantly depending on whether the
block-level element had non-zero vertical borders or padding.

Why aren't self-collapsing elements prevented from collapsing their own

Then they would frequently affect the layout, in very, very common
situations (such as an empty P element in amongst non-empty P elements).
  With margin collapsing, they can often avoid having an impact.

So we're stuck with them.  Why are they problematic?

For one thing, there's no natural place that can be identified as their
border box.  And the border box position is necessary to determine where
to place any floated and absolutely positioned children.

By convention, if a self-collapsing element collapses its margin with
its parent's top margin, then its top border edge position is defined to
be that of its parent; and if it doesn't, its top border edge position
is defined to be where it would be (relative to the canvas) if it had a
non-zero bottom border (noting that the temporary assumption of a
non-zero border changes how margins collapse around the element).

That convention sound kind of arbitrary!  What gives?

Well, in the first case, it's the only way of ensuring that the
self-collapsing element's border area lies within the parent's border
area.  It would be strange if the element's floated children ended up
higher than its parent's top border!

In the second case, it /is/ kind of arbitrary.  The position has to be
somewhere in the margin lump in which it participates.  It would be
strange if it were higher than where it would be if the element actually
had a non-zero border top.  Likewise, it would be strange if it were
lower than where it would be if the element actually had a non-zero
border bottom.  Based on the results of test cases, the lowest position
within those two bounds was chosen (although only after many years of
the spec choosing the /highest/ position!).

And how does all this relate to clearance?

If a self-collapsing element has 'clear' set, we have to determine
whether its top border edge is below the bottom outer edge of all
relevant floats.

Easy, right?  The convention gives us the top border edge position!

Yes... but oddly it's not /that/ position that's used.  It's a different
position, this time defined as where it would be (relative to the
canvas) if the clearing element really did have a non-zero *top* border.


Because there's an error in the spec!  Stay tuned for the follow-up, in
which we demonstrate precisely why this part of the spec is just silly...

Anton Prowse

Received on Sunday, 15 August 2010 07:31:50 UTC