Forum Moderators: not2easy
The clear property dictates that the top edge of the element cannot be above the bottom edge of any floated elements preceding it in the document on the indicated side (left, right, or both.) So clear:left means you are going to push this element below any previously floated elements on the left side of this element.
The catch is "any" preceding it. So you have a floated left and right column, followed by main content - the standard "faux columns" approach:
#left { width: 150px; float: left; }
#right { width: 150px; float: right; }
#content { /* whatever, nothing really needed */ }
<div id="left">left</div>
<div id="right">right</div>
<div id="content">content</div>
But within the content you have a few items you need to clear for one reason or the other. If the content area is shorter than the columns, this will clear all the way to the bottom of the column (left, right, or both, depending on how you set clear.)
<div id="content">
<img style="float:right" src="image.gif">
<p>content content content content content content</p>
<div style="clear: both"></div>
</div>
The above example clears all the way to the bottoms of the longest column, #left or #right. So obviously this is not the right way to do this.
How would you "clear" #content so it wraps the picture without using a clearing div? I've experimented with overflow and just floating the parent (a floating div contains all it's children) but it doesn't seem like these are the correct ways to do this, and have been having complaints from IE 6.
Take the following scenario. Let's call the left and right columns ad columns, that applies for the exercise:
¦........... header ................¦
_____________________________________
¦left col¦......row 1.....¦right col¦
¦........¦......row 2.....¦.........¦
¦........¦......row 3.....¦.........¦
¦........¦......row 4.....¦.........¦
¦........¦......row 5.....¦.........¦
¦........¦......row 6.....¦.........¦
_____________________________________
¦........... footer ................¦
The headers and footers are easy. Pick your width, set margin auto, and add a clearing div below the header and prior to the footer.
<div style="clear:both"></div>
While this is a handy tool for clearing the page for the next "row" of elements, it can present problems for complex nested content, and easily becomes a crutch that fails to work in more complex layouts.
Unless you want to use the evils of fixed width and absolute positioning, the usual way to do the columns is to float the side columns left and right, with the center column having left and right margins equal to or just greater than the columns (see post #1.)
It's when you get content that's the cheese begins to bind, the wicket gets sticky. Say, for example, you have ads dancing down the left and right, each a contained unit, and the center section is rows of search results.
If you attempt to clear the center rows, they will do just what you tell them - they will clear all the way to the bottoms of the ads. So you've got this huge white space at the top of the center column, and content doesn't begin until you get below the ads. This is due to the way a clear works: it sets a rule that the topmost edge of the cleared element cannot touch any item before it on the left, right, or both, depending on how you set it. Since the ads come first in the document (again, see post #1) this means if you use a clearing div anywhere in the center column, it's going to shove all content down below the ad columns.
The solution(s) I came up with involve floating the center-row elements, and using a combination of floated child elements and/or setting overflow: hidden on the outer floated element. This is based on a simple rule: a floated element will contain and clear it's floated children. The following is "basic" for concept demonstration only.
<style type="text/css">
.row { float: left; width: 100%;margin-bottom:12px; border: 1px solid #000000; }
.row_top, .row_foot { float: left; width: 100%; overflow: hidden; background-color:#dddddd; }
.hd_left,.foot_left { float: left; width: 20%; margin: 0; padding: 6px; }
.hd_right, .foot_right { float: right; width: 20%; margin: 0; padding: 6px; }
.hd_center { width: 100%; text-align: center; margin: 0; padding: 6px; }
</style>
This is your "center column" and the floated "row container:"
<div style="margin: 0 300px 0 300px;">
<div style="float: left; border: 1px solid #ff0000;">
<div class="row">
<div class="row_top">
<h4 class="hd_left">left text</h4>
<h4 class="hd_right"> right text</h4>
<h3 class="hd_center">some in the center</h3>
</div>
<p style="text-align: center;">
Some text some text some text
</p>
<div class="row_foot">
<p class="foot_right">more text to the right</p>
<p class="foot_left">natural flow on the left</p>
</div>
</div>
<!-- .... repeat this "row" as many times as required -->
<!-- End the wrappers -->
</div>
</div>
This solution needs tweaking for IE7/IE6, concept only. You have to play around with it, but basically:
- float left and right columns, set margins on center column to those widths
- float a wrapper in the center column, possibly setting overflow:hidden to get IE 6 to play along
- construct the "row" boxes of floated elements, also setting overflow: hidden if required.
Using these concepts and wearing the F5 key off three computers here, I've managed to come up with two columns left and right of variable depth, and a center column that contains 1 pixel borders with 12px radius rounded corners (which is a floating nightmare in itself.) The center column is sometimes short, sometimes long, and contains everything from the row samples above to regular flowing content. Not a table or clearing div in sight save the ones below the header and above the footer.
Maybe this can be useful to those struggling with floats and clears, or maybe one of you out there has a better way.