Viewing: One Entry

Firefox, CSS and floats: Where’s my background?

September 26, 2008 @ 22:53:15

This is one of those absurd situations that result in far too much effort and stress (if you ask me). It goes like this: You want to create a layout with a couple columns. Those columns are set inside your “container” with a pretty background color or nice border. Wrap a couple <div> elements, float one left, the other right, and add your border/color. Right? Check it out in IE and things look as you expect. But when you look at the results in Firefox, you’ve lost your background! Or that distinguishing border is now lumped at the top as a single, less-than-appealing line! What happened?

There are countless solutions to this available via the normal searching mechanisms. I have to give credit to my first encounter of the solution I like the best: a “Background height problem” forum post with the solution being the very first response. The <img> element at the bottom of poster’s content could be modified with the “clear: both” style applied to it. The solution also points to this excellent article, “Clearing a float container without source markup“, which goes into some great detail (a must read).

So here’s my quick tutorial on the matter. For this to be worth while, you’ll need to be following along in Firefox. And again, for more details, please read the “Easy Clearing” article linked to above.

1. The Setup

A quick and easy two column design starts with three divs: the container, the left column and the right column (Amen).

<div id="container">
 
	<div id="left">
        <p>To the left.</p>
	</div>
 
	<div id="right">
        <p>To the right.</p>
	</div>
 
</div>

Let’s add some styling to make them distinguishable from each other. We’ll give the container a think, red dotted border. The left side gets a normal green border and, for the right, something blue.

#container
{
    border: thick dotted red;
    width: 610px;
}
#left
{
    border: thin solid green;
    width: 400px;
}
#right
{
    border: thin solid blue;
    width: 200px;
}

Here’s what we’ve got so far. I like how the big red dots seem to hug all the content, don’t you? Also notice we’ve given explicit width values, which are required for floating elements (added next).

2. Lorem Ipsum Floats

Let’s columnize it with a quick edit to our CSS. The “left” div will float left, and the “right” div will float…let me think….oh yeah…right!

#left
{
    float: left;
    border: thin solid green;
    width: 400px;
}
#right
{
    float: right;
    border: thin solid blue;
    width: 200px;
}

I can’t wait to F5 this sucker and see our cool new columns.

Whoops. No more hugging!?!?

When an element is given the float property, it’s removed from the normal layout flow of the document.

From W3C, 9.5:

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float didn’t exist.

The container has nothing in it besides those two floating elements. Because they are no longer “in the flow”, that container essentially has nothing to define just how tall it needs to be. Let’s fix it.

3. Clearing House

They keyword here is “clear”. CSS2 defines the clear property as a way of specifying that a block element should not fall along the sides of a previous float. You can tell it to clear:right so that it pushes below any previous right floaters. You can tell it to clear:left to push past the southpaws. Or, as we’ll do here, you can tell it to clear:both, which basically means “Stop pushing me around”.

Now, at this point, one option is to manually insert a new, empty div immediately after the “right” column. We style it with clear so that it can ignore the two previous floats. This pushes it past them to the bottom of the container, which now must stretch out to fill all this new space. VoilĂ , we have a fix.

Here is our original HTML modified as an example, with the new div’s styling done inline:

<div id="container">
 
	<div id="left">
        <p>To the left.</p>
	</div>
 
	<div id="right">
        <p>To the right.</p>
	</div>
        <!-- Let's name him "stretch" -->
        <div style="clear:both"></div>
</div>

But it doesn’t have to be that way. I mean, do you want to manually insert extra cruft into your page like that? As an alternative, have you considered our shiny new model? The :after pseudo-element? It’s CSS that injects content for you! (Aside: On some level this seems wrong to me. Why would they create a method for the presentation mechanism to insert content? But then again, who cares. It’s there and it’s pretty cool, so let’s use it.)

Here is the new addition to our styling family:

#container:after
{
    content: "";
    clear: both;
    display: block;
    height: 0;
    visibility: hidden;
}

Now gander at what you have created. The hug is back!

Adding :after to an element’s style will literally add something (the “content“) after it. Examples I have seen use a period character for the content value (e.g. content: "."), which then absolutely requires that you specify a zero height and no visibility (otherwise the period would be displayed at the end of your content). But using an empty string seems to work just as well, and the two extra rules (height and visibility) aren’t needed. However, it seems prudent to just err on the safe side and go with both.

4. Handling the Exceptions

I only covered the Firefox relevant pieces here (which is the majority of it). But if you decide to use this technique to fix your missing background/borders, please read Clear a float container (linked to yet again for good measure) to view the extra information you’ll need to account for other browsers.

No Comments

Comments can be removed at any time for any reason. Thanks.