(Advanced question) Clearing floats without the normal clearfix method

Disclaimer: By all accounts, what I’m asking may not be possible…I’ve spent a while playing with different ideas without finding the perfect solution.

I’m in the process of writing some helper classes for a client’s site. These perform basic functions like allowing them to implement 2 or 3 column layouts within the main content div for page variety, etc. Now, the markup for these helper classes needs to be as simple as possible. This organization has people coming in and out with various levels of web knowledge, some who would soon as skip complex structural markup they don’t understand in favor of a table to achieve their layout results.

That being said, this is the issue I’m running into. Within the flow of a page’s content, I’d like to give them the option to split select content into columns with minimal markup, like so:


<p>Lots of other content above this.</p>
<div class="one-half left">
  Left column
</div>
<div class="one-half right">
  Right column
</div>
<p>Some more content below this.</p>

.one-half { width: 49%; margin-bottom: 0.5em; }
.left { float: left; margin-right: 1.22%; }
.right { float: right; }

Of course, the problem is that if the left column is longer than the right, the content below will jump up underneath the right column when I’d like for it to wrap to a new line instead.

Now, the most obvious solution to the problem (without adding extra markup) is to apply “clear: both” to the block-level elements so they clear the columns completely. However, that becomes a problem when they go to float an image within the flow of content and all the elements stubbornly wrap to a new line.

I could always wrap a parent div around the columns and apply the clearfix method, but I’d like to avoid that if possible to keep my markup simple.

Another possible solution is using a snippet of javascript to automatically wrap the columns with a clearfix div, but that’s not really ideal either as I’d rather use pure CSS.

Does anyone have a creative way to solve this problem with CSS?

The first thing that occurs to me is that you could use something like this:

div.right + p {clear: both;}

That means that any <p> element that follows a div with class=“right” will be set to clear: both;.

Of course, the code can be simplified to this:

.right + p {clear: both;}

or you could instead use

.one-half + p {clear: both;}

Ralph, exactly the sort of creative solution I was looking for!

I ended up using this code to achieve my result:

div.right + * { clear: both; }

Of course, that doesn’t work in IE6 (which I unfortunately have to support at least a little), so I used this line of jQuery to spot-fix the lack of support:

$(".ie6 #content div.right").next().css("clear","both");

Quick and simple–I like it!

I’d do it much more simply and without javascript like this :slight_smile:


.one-half {
    width: 49%;
    margin-bottom: 0.5em;
    display:inline-block;
    background:blue;
    vertical-align:top;
}
* html .one-half {display:inline}/* ie6 inline block hack*/
*+html .one-half {display:inline}/* ie7 inline block hack*/
.left {margin-right: 1%}


That avoids all float clearing issues.

I’d probably just make ALL P “clear:both” since it’s unlikely you’d be floating P… Assuming there’s a parent wrapper around those P and floated DIV.

NOT that I would EVER have the classes “left” and “right” since those do not say what the content is, and says how they appear; at which point you might as well go back to using HTML 3.2 and “align”.

Of course if they’re both half width and were to have padding around them (which I’d assume they would) I’d be floating them both the SAME direction and margin/pad just one side. That avoids the potential IE perfect-width float drop. That or if using % widths and padding tags inside them instead (since you can’t mix % width with padding/margin reliably) I’d float them both left and give the right one a negative margin to prevent that same IE width bug.

But again, why layout without content is usually the start of the path to failure.