More Float Examples

Float gets a lot of press. Smashing Magazine gives a thorough summary here.

On this page, I'll demonstrate a few basic issues that might bedevil you, starting with float's ability to flow out of its parent element, or box.

Overflowing the Parent

Below is a DIV with a white border. It contains (or is the "parent" of) two paragraphs: a longer one, floated to the RIGHT, and a normal paragraph.

This right-floated paragraph is longer than the normal paragraph (which wraps around it on the left).

Float causes it to flow past the bottom of its parent box.

This normal paragraph sets the length of the parent box.

Although this paragraph is outside the DIV that "contains" the float, it wraps, too.

Look at this paragraph's top margin. You see it creates space beneath the normal paragraph above, but not beneath the floated paragraph. The bottom of the float extends well past the top margin.

Here's why. The browser puts the top edge of each normal box below previous normal boxes (after calculating the room needed for their combined margins and padding and such).

Floats escape this calculation. The browser determines the size of a floated box, shifts it left or right, then adjusts the width of subsequent boxes to fill the space created by the shift. The margins between normal boxes are preserved, but they aren't honored with respect to the float. (Otherwise, text could never wrap around a float — it would just be pushed beneath it.)

So overflowing the parent is the correct, often desireable behavior — as the mock newsletter below illustrates.

CSS Gazette

This issue of the CSS Gazette illustrates the benefit of float overflowing its parent.

Clear and Margins

This correct behavior can be a nuisance when you want to create a couple of columns, followed by full-width text.

The next DIV floats a paragraph to create 2 columns. It's followed by a "cleared" heading (set to "clear: both").

Column 2.
This is a right-floated paragraph and is longer than the normal paragraph on the left. As before, it flows past the bottom of its parent container.

Column 1
A short, normal paragraph.

This "cleared" heading marks a new section

The heading above is "cleared," so it doesn't wrap around the float. But the heading is too close to the floated paragraph. As shown above, margins only apply between normal boxes — a top margin creates no space between a "cleared" box and a floated one.

How do you restore the spacing?

2 Short-Sighted Solutions

<br />   The least-desirable solution is to add a break inside the heading. This clutters up your structural markup with a tag that exists solely for formatting purposes. It makes no semantic sense to start a heading with a line break.

padding   Padding adds space between a box's border and its contents. Margins add exterior space (ignored by floated elements), but padding adjusts interior space.

So padding can separate cleared boxes from floats. A rule such as h3 {padding-top: 2em} would do the trick.

Column 2
This is a right-floated paragraph.
.
.
.
.

Column 1
A short, normal paragraph.

This "cleared" heading has extra top padding

Now the heading has some extra separation from the float.

But this solution falls short if other headings on the page occur beneath normal boxes. They would have an extra large gap (due to the combined size of their margin and their padding).

To solve this, you could simply set their top margins to 0, and rely only on padding for spacing. But see what happens if you then add a top border to your headings:

Column 2
This is a right-floated paragraph.
.
.
.
.

Column 1
A short, normal paragraph.

This "cleared" heading has extra top padding and a border

We're more or less back where we started. Now the problem is the space between the heading's border and the float.

The above solutions treat the heading as the problem. But the challenge is to overcome the normal behavior of the float. We want to prevent it from overflowing its parent.

Overflow

The "overflow" property addresses this conditon. Its default value is "visible" — longer children visibly overflow a shorter parent (as shown above).

Overflow can also take these values:

When a parent contains a child that exceeds its boundaries, "overflow: auto" does one of 2 things.

If the parent has a set height shorter than its children, the browser adds scrollbars to the parent. Like this:

The DIV below has "height: 75px" and "overflow: auto" applied.

Column 2
This is a right-floated paragraph which cannot overflow its parent DIV.
.
.
.
Float ends here.

Column 1
A short, normal paragraph.

Note that the floated paragraph is now entirely enclosed by the parent DIV.

If the parent's height is not set, the browser resizes the parent to fully enclose its longest child, even if that child is floated.

This DIV has "overflow: auto" applied, but no "height" specified.

Column 2
This is a right-floated paragraph which cannot overflow its parent DIV..
.
.
.
Float ends here..

Column 1
A short, normal paragraph.

This heading has extra space, even with a top border

The heading's top margin is added as usual to the bottom of the preceeding DIV, which is now lengthened sufficiently by "overflow: auto" to preserve the desired space.

For the same reason, the heading no longer needs to be "cleared." It falls directly beneath a "normal" box.

The "Block-Formatting Context" and Clear

The next issue concerns clearing an element after multiple "floats".

Say you've created a page split into two columns: a "menu" DIV on the left, and a "content" DIV on the right. You've floated the "menu" to the left. To prevent the "content" from wrapping underneath your "menu," you give "content" a wide left margin. Like so:

Menu
Item 1
Item 2
Item 3
Item 4

Main Content

These are normal paragraphs in the "content" DIV.

So far so good.

The problem arises in the next example when you try to clear a float, added to the main content.

You decide to add a Quote of the Day to the main content. You float the Quote box to the right. You want the first paragraph to wrap around the quote, but (who knows why) you want the 2nd paragraph to "clear" it. So you apply "clear: both" to the 2nd paragraph.

Menu
Item 1
Item 2
Item 3
Item 4

Quote of the Day

This paragraph wraps normally.

This paragraph has "clear: both" applied.

The "clear" opens up a huge gap above the preceding paragraph.

How come?

The large space above the 2nd paragraph is caused by the "block-formatting context" in which the "clear" occurs.

According to the CSS standard, "clear" applies to all prior floated elements inside the same "block-formatting context." It doesn't matter if they're visually aligned or not.

The problem here is that the "menu" DIV and the "content" DIV are both in the same context, so the "cleared" paragraph is pushed beneath the bottom edge of the floated menu.

Overflow (again)

One solution looks similar, but works for a different reason.

If you apply "overflow: auto" to the entire "content" DIV, the problem disappears. In the next example, the "content" DIV now has "overflow: auto" applied.

Menu
Item 1
Item 2
Item 3
Item 4

Quote of the Day

This paragraph wraps normally.

This paragraph has "clear: both" applied.

It now clears only the Quote of the Day but not the menu.

Why oh why?

There are a handful of CSS properties that establish new block-formatting contexts:  absolutely positioned boxes, floated boxes, inline blocks, table cells and captions, and "overflow" (when it's set to something other than "visible").

By setting "overflow: auto" on the "content" DIV, you create a new block-formatting context. The browser then only considers floats inside "content" when it clears the 2nd paragraph.

(or) Position: Absolute

The other option is to recast your layout. Rather than "floating" your "menu," you could "position" it.

"Position: absolute" removes the "menu" DIV from "normal flow" entirely. Hence, the clear on the 2nd paragraph is limited to floats inside "content," whether or not you alter content's "overflow."

On the other hand, when faced with the next situation, you might want to stay with "float."

Short Backgrounds

On some pages, your content might be shorter than your menu. If "content" has a background color or image, it can look unbalanced.

Menu
Item 1
Item 2
Item 3
Item 4

Quote of the Day

Short content.

You can lengthen "content" in a couple of ways.

Min-Height

If your menu never varies in length, you can set a minimum height for "content" to force it to extend at least as far as "menu."

However, your menu might vary between sections of a large site. Or, you might use menus that expand and contract. Or, you might use a liquid layout that causes the text in your menu to wrap. Any of the above would prevent you from calculating "min-height" in advance.

Generated Content

Position Is Everything describes this clever solution. You can generate a tiny element at the end of "content" using CSS2's "after" property.

Only limited formatting properties apply to generated content, but you can display it as a "block" and force it to "clear."

Here's the result.

Menu
Item 1
  sub A
  sub B
Item 2
Item 3
Item 4

Quote of the Day

Short content.

Regardless of the length of the menu, the generated content now "clears" it, dragging "content's" background and border along for the ride.

However, this solution can re-introduce the problem we saw above. It requires "content" and "menu" to be in the same block-formatting context. Hence, a cleared element on a short page will drop below "menu" again.

Menu
Item 1
  sub A
  sub B
Item 2
Item 3
Item 4

Quote of the Day

Short content.

A 2nd paragraph — and the pesky "clear" issue, again.

Work-Around

You've arrived at an impasse. You need "menu" and "content" to share and not share the same block-formatting context — the former for the sake of content's background, the latter for the sake of its 2nd paragraph.

One fix is to

Now you can apply "overflow: auto" to "content" to confine its block-formatting context. This prevents the 2nd paragraph from clearing the menu.

Here's the result. (I've added a dashed border around "content" so you can see where it really ends.)

Menu
Item 1
  sub A
  sub B
Item 2
Item 3
Item 4

Quote of the Day

Short content.

This paragraph "clears" the Quote, but not the menu.

With "wrapper" in the same block-formatting context as "menu," its generated content clears "menu" and pulls its background and border along with it, as before.

Another fix is to, um . . . well there must be several. And I assume they're better than this one.

Rob Weller