Overcoming Float Problems

As you get more adventurous with CSS, you'll probably encounter—like many web designers before you—some of the weird intricacies of working with floats. This section describes a few common problems and their solutions. (And if you ever stumble upon a problem not listed here, you can always take it to one of the online forums or discussion lists in Appendix C.)

Note

When it comes to designing pages that work in Internet Explorer 6, there are even more potential pitfalls. So many, in fact, that this chapter has a separate section dedicated to dealing with that one browser. See Handling Internet Explorer 6 Bugs.

Floats are powerful design tools because they let content flow around them. Floating a photo lets text below it move up and wrap around the image (Figure 12-1). When you're creating float-based column designs, though, sometimes you don't want content to move up and next to a floated element. For example, you frequently want to keep copyright notices, contact information, or other housekeeping details at the bottom of your web page, below all other content.

In the two- and three-column designs you've seen so far, if the main column is shorter than either of the floated sidebar columns, a footer can move up and around the left floated column (Figure 12-7, left). To make the footer stay down below the sidebars, you can use the clear property (Stopping the Float). This property prevents an element from wrapping around floats. You can make an element drop below a left-floated object (clear: left;) or a right floated object (clear: right;). For footers and other items that need to appear at the bottom of the page, you should clear both left and right floats, like this:

#footer { clear: both; }

Another problem occurs when you float one or more elements inside a non-floated containing tag like a <div> tag. When the floated element is taller than the other content inside the div, it sticks out of the bottom of the enclosing element. This snafu is especially noticeable if that tag has a background or border. The top of the web page in Figure 12-8 shows a <div> tag that has an <h1> tag and two columns created by floating two divs. The background and border, which appear only around the <h1> tag, are actually applied to the entire enclosing <div>, including the area where the two columns are. However, since the columns are floated, they pop out of the bottom instead of expanding the borders of the box.

A similar problem happens in the bottom example in Figure 12-8. In this case, each image is floated left inside a containing <div> that has a border. Because the images are taller than their boxes, they pop out of the bottom. Unfortunately, this example is even worse than the previous one, because each image causes the image below it to wrap to the right, creating an ugly staggered effect.

You have many ways to tackle the problem of these renegade floating elements. We'll cover all of these techniques below, because it's good to have more than one solution under your belt.

HTML tables aren't great for web page layout for several reasons. They add lots of code, are difficult to update, and don't work well on alternative browsers like those used by cellphones. But tables have one thing going for them in the layout department—the ability to create columns of equal height. Equal-height columns let you add a background color or graphic to one column and have it fill the entire height of the page. The backgrounds of the two sidebars in the top image of Figure 12-10 fill the screen height, creating solid, bold stripes on either side of the page.

CSS floats, on the other hand, fall a bit short in this regard. Table cells in a row are always the same height, which isn't true of divs. The height of a float is usually dictated by the content inside it. When there's not a lot of content, the float is not very tall. Since a background image or background color fills only the float, you can end up with solid-colored columns that stop short of the page bottom, as in the circled areas in Figure 12-10, bottom.

As with most problems related to CSS, there's a workaround. The secret is to add background images to a tag that wraps around the stubby sidebar and the other columns on the page. Say your HTML has two <div> tags that contain the content for a left sidebar and the page's main content:

<div id="sidebar">Sidebar content here</div>
<div id="main">Main content for page, this column has a lot of text and is
much taller than the sidebar.</div>

The sidebar <div> is floated to the left edge of the page and has a width of 170 pixels. Because there's less content in the sidebar, it's shorter than the main text. Suppose you wrap that HTML in a wrapper <div> tag, like so:

<div id="wrapper">
<div id="sidebar">Sidebar content here</div>
<div id="main">Main content for page, this column has a lot of text and is
much taller than the sidebar.</div>
</div>

That outer div grows to be as tall as the tallest element inside it, so even if the #main div is very tall, that wrapper div will be just as tall. Here's the magic: Create a style for the wrapper <div> with a background image the width of the sidebar, in the background color you want for the sidebar. That way, if the background image tiles vertically, it forms a solid bar the height of the wrapper <div> (Figure 12-10, top).

#wrapper { background: url (images/col_bg.gif) repeat-y left top; }

Web browsers display that background image directly under the sidebar, creating the illusion that the sidebar has a background color. In essence, you create a "faux column" in the words of Dan Cederholm, the fellow who first publicized this technique.

Reproducing this result for two columns is just a little more involved. First, add two wrapper divs:

<div id="wrapper1">
<div id="wrapper2">
<div id="sidebar1">Sidebar content here</div>
<div id="sidebar2">Second sidebar</div>
<div id="main">Main content for page, this column has a lot of text and is
much taller than the two sidebars.</div>
</div>
</div>

If the first sidebar appears on the left side of the page and the second sidebar appears on the right side, you create two styles. Apply one style to the first wrapper <div> tag to add a background to the left sidebar; apply one to the second wrapper <div> to add a background to the right sidebar (Figure 12-11, bottom).

#wrapper1 { background: url(images/col1_bg.gif) repeat-y left top; }
#wrapper2 { background: url(images/col2_bg.gif) repeat-y right top; }

When adding a background image to the right-hand column, make sure you position the background image in the top right of the second wrapper, so that it falls underneath the second sidebar on the right side of the page.

Suddenly, one of your columns simply drops down below the others (Figure 12-12, top). It looks like there's plenty of room for all the columns to coexist perfectly side by side, but they just don't. You've got the dreaded float drop.

A floated column drops down because there's not enough room to fit it. Be careful if you set widths for each column. If the available space in the browser window (or the containing block in a fixed-width design) is less than the total widths of the columns, then you're asking for a float drop. Also, keep the CSS box model in mind: As discussed in the box on Margin and Padding Shorthand, the width of an element displayed in the browser window isn't the same as its width property. The displayed width of any element is a combination of its width, left and right border sizes, left and right padding, and left and right margins. For the columns to fit, the browser window (or containing block) must accommodate the combined total of all those widths.

Take, for example, the simple three-column layout in Figure 12-12. As you can see in the top example, the three columns don't fit. Here's a breakdown of the math behind the problem:

While miscalculated column widths are the most common cause of dropping floats, they're not the only cause. Here are a few other culprits:

Bottom line: Float drops are always caused by not enough room to hold all of the columns. Rather than striving to use every last pixel of onscreen space, give all your elements a little more wiggle room. Get in the habit of making the overall column widths a bit smaller than necessary, and you'll spend less time troubleshooting float drops.