Jump to navigation.

In our last article we looked a little closer at one of the methods for creating layouts with CSS: absolute positioning. Today we're going to try to illustrate another option: floating elements. At least as misunderstood as positioning, but often much more useful.

Everything Does Not Float

Panta rhei, said Herakleitos, everything is floating. Even if the underlying philosophy, that everything is constantly changing, very much applies to the web, it doesn't apply to today's topic. To make an element float we have to say so explicitly, for instance like this: float:left

When we make an element floating, we ask the browser to shift it sideways, either to the left or to the right, as far as it will go.

Those who really understand the previous sentence already know half of what you need to know to use floats. There are three important pieces of information in that sentence, so let us examine them before we tackle the other, somewhat trickier, half.

Step Aside Please

The first thing we need to remember is that a floating element is shifted either to the left or to the right. It is not possible to make an element float in the centre, something that often is frustrating for beginners. If you think about it awhile, it's fairly clear why it is so. Why? To answer that we have to jump ahead of ourselves a bit and see what happens when we create a floating element in our document.

A common usage for floats is with images. We want to insert an image and make the text flow around it. With CSS we don't make the text floating, but the image. If the image has float:left the text will flow on its right side. If the image has float:right the text will flow on its left side.

If it were possible to make an image float in the centre, the browser would have to make the text flow on two sides of it. Contrary to the two simpler cases, it's far from clear how that would be done. Should the text lines split in two to make room for the image? Or should the text suddenly split into two columns? Unless the image is very small, it is also likely that the available space on either side of the image won't be enough for long words.

The second important piece of information in the basic rule above is that a floating element is only shifted sideways. We have seen optimistic attempts to specify float:top in order to move something to the top of the page.

In order to really understand float theory you have to understand what a line box means in CSS. Unfortunately, that in turn requires you to understand what is meant by an inline box, which is way too complicated to explain in any detail here. If you're interested (and slightly masochistic) you can try to decipher the explanation in section 9.2.2 of the CSS 2.1 specification.

An inline box is generated by those elements that aren't block-level, such as EM. Furthermore, an anonymous inline box is generated by text nodes inside block-level elements. It's not too hard to imagine that each block-level element consists of a rectangular box. An inline box can also be viewed as such a box, although it obeys slightly different laws than its cousin the block box.

A line box is an imaginary rectangle that contains all the inline boxes that make up a line in the containing block-level element. It is (at least) as tall as its tallest line box.

We won't dig deeper into the box theory than this, so we'll entertain the notion that a line box is an imaginary box that encompasses an entire line of text and (non-floating) images. The reason for this digression is that we need to know that the upper edge of a floating box is aligned with the upper edge of the current line box (or with the bottom edge of the previous block box, if there is no line box).

It is also good to know that all floating elements automatically become block boxes. Thus it's not necessary so say display:block for a floating element. More about that later.

Okay, so what does this mean in plain English? It means that a floating box can never end up above the upper edge of the line where it's created. Or, in other words, that a floating element is only shifted sideways, but we knew that.

The Buck Stops Here

The third important detail in the basic rule above is the words as far as it will go. When we float an element it is shifted to the right or to the left until it reaches the edge of the containing block. If we then float another element nearby in the same direction, it will be shifted until its edge reaches the edge of the first floating element. In other words, it will settle beside the first element. If we float more elements in the same direction they will stack up, but sooner or later we'll run out of space. We'll look at what happens then in a moment, but we need another dose of theory first.

What Is Really Happening?

Just like absolutely positioned elements, floats are removed from the document flow. They don't affect subsequent block-level elements. However, the line boxes that are generated next to a float are shortened. Think of it as if they're just making room, horizontally.

Let's say that we have a number of text paragraphs. In the first paragraph we want to insert a tall, but narrow, image, and we want the text to flow on the right side of the image. So we set float:left on the image.

The line boxes that are generated by the text in the first paragraph are shortened so that they start at the right edge of the image and stretch to the right edge of the paragraph box. But the image is so tall that the text of the first paragraph ends before it reaches the bottom edge of the image.

The next paragraph, a block-level element, isn't affected by the floating image. It has been removed from the document flow. Its block box is created at the usual distance from the first paragraph's block box, with consideration to margins and all that. Here's the beauty of it: the second paragraph's line boxes are also shortened, just as in the first paragraph.

And so it goes on until the text lines reach the bottom edge of the image. Then the line boxes no longer need to be shortened, and the text continues below the image.

One, Two, Three, Many

Let's look back to the example where we let a number of elements float in the same direction. For each floating element, our line boxes are shortened, and eventually there isn't enough space for the next float.

We now see the next important trait of floats: when there is insufficient space on the line, they are shifted downward until they fit. This can be extremely valuable in layouts that need to work in different window sizes. If the columns are floating, they are rendered side by side in a wide window, or stacked vertically in a narrow one.

Er … Mate, It's Hanging Out

As we just saw, a floating element can extend past the bottom edge of the block-level element where it was created. A block box is not extended to enclose its floating children, since that would make it impossible to achieve the smooth effect we desired in the example above with the tall, narrow image. (A floating element is extended to enclose its floating children, though.)

Sometimes this is the desired effect, sometimes it's not. Fortunately, there's a way to cancel it. We can force an element to drop below all floating elements via the clear property. If we specify clear:left the element drops below all elements floating on its left side. With clear:both we can make sure that an element drops below all floating elements that would otherwise affect it.

For a block box the shift is accomplished by incrementing its top margin until the upper edge of the element is below the lower edge of all floating elements created earlier in the document. (Don't be embarrassed if you have to read the previous sentence several times to understand it, this is tricky stuff.)

For inline boxes it's even more complicated, but the result is the same. And floating elements can set the clear property, too…

Why do we need to know all this? Because it has consequences that would otherwise seem quite inexplicable. Let's say that we want to make sure that an H2 heading doesn't end up next to a float. So we set clear:both on it. Let's also assume that we want a certain margin between any float and the heading, so we set margin-top:1em. It is now very possible that we get into a situation where the heading butts up against the float. Why?

Remember that floats don't affect subsequent block boxes. If we hadn't set the clear property of the heading, it would have been created 1em below the previous block-level element (and the heading would have ended up next to a left-floating element extending past its containing block). Since we do set the clear property, the top margin is increased until the upper edge of the heading is below the bottom edge of the floating element. But no more!

If we want to ensure some space around a floating element, we have to set the margins on the floating element itself.

Floating Columns

How can we use floats to create a multi-column layout, and why is this sometimes better than absolute positioning?

If we enclose each column in a DIV element with float:left they will appear side by side, just as we expect columns to do. If we then want a full-width footer to be shown at the bottom, no matter which column happens to be longest, we only need to set clear:both on it.

In a floating layout we want to specify the column widths in percents. Here's some good advice: don't specify the percentages so that they add up to 100% exactly (e.g. 60/40 or 25/50/25). The slightest rounding error will then cause the right-most column to drop below the others. Instead, use 60/39 or 25/49/25, to be on the safe side.

A fully liquid layout has some inherent problems. In modern browsers (read: anything but IE) we can set a min-width (preferably in ems) for each column. In a narrow window, one or more columns may drop below the others, which may not be all that pleasing aesthetically, but it's often more user-friendly than having to scroll horizontally.

So we solve the footer problem with liquid columns, something that just cannot be done with absolute positioning. We do, however, have another problem that is easier to solve with absolute positioning: source order. It is often desirable to have the main content of the page as early as possible in the markup. Less relevant things like navigation and ads can come later. But with floats we are constrained to specifying them in the proper order. If we want a menu on the left, ads on the right, and the content in the middle, the content can't come first. Or can it…?

It's possible, but it's not trivial. Let's say that we want the content first, then the left menu and the ads last. Let's also say that we want to use the proportions 25/50/25. Furthermore, we want a border between the columns. In order to achieve this we need to add a couple of extra DIV elements to group things. The structure will be as follows:

<div id="outer">
  <div id="inner">
    <div id="content">Content</div>
    <div id="menu">Menu</div>
  </div>
  <div id="sidebar">Ads</div>
</div>

The outer container consists of an inner container (on the left) and the ad sidebar (on the right). The CSS looks like this:

#outer {
  margin:0 25%;
  border:1px solid #000;
  border-width:0 1px;
}

The left and right margins are set to 25% to make room for the side columns, and then we add a thin black border on either side.

The inner container consists of the content column (on the right) and the menu (on the left). The CSS:

#inner {
  float:left;
  width:99%;
}

#content {
  float:right;
  width:99%;
}

#menu {
  float:left;
  width:50%;
  margin-left:-49.9%;
}

The inner container itself is thus floating to the left and occupies almost all of the outer container's width – except for the margins, of course. The content column is floating within the floating inner container, occupying most of its width.

The menu floats to the left, so that it ends up next to the floating content column. Its width is supposed to match the outer container's left margin, which is set to 25%. But if we specify the menu width as a percentage, it means a percentage of the inner container's width, not of the page width. The inner container's width is (almost) half the window width (99% of 100% minus two margins of 25%), so the menu's width is approximately 25% divided by .5, which equals 50%. Phew!

As if this weren't enough, the menu also has a negative left margin that is almost as large as its width. The operative word here is almost. The negative margin causes the menu, which only has 1% of the inner container's width to live in, to be shifted outside the inner container and end up in the outer container's left margin, which we created for that specific purpose.

So why don't we set the left margin to -50%? Because we can't move the menu completely out of the inner container. If we do, it won't exist in the inner container anymore, and if the menu column happens to be the longest, it will overwrite a subsequent footer. Since this technique causes the menu to actually overlap the inner container a little, we should give any child elements of the menu a right margin to create some space.

The CSS for the sidebar column is similar to the one for the menu:

#sidebar {
  float:right;
  width:50%;
  margin-right:-49.9%;
}

The sidebar is after the inner container in the markup. The inner container is left-floating and occupies 99% of the centre. Since we float the sidebar to the right and give it a negative right margin, we shift it out into the margin just like we did with the menu. The width is computed in the same way and as with the menu we should give any child elements some left margin to prevent them from overlapping the border.

If we try this now, it won't work at all. Why? Since all components are floating and thereby removed from the document flow, the outer and inner containers have no content at all. The remedy for this is to add a couple of equalising elements that make sure the containers actually contain their floating children:

<div id="outer">
  <div id="inner">
    <div id="content">Content</div>
    <div id="menu">Menu</div>
    <div class="cleared">&nbsp;</div>
  </div>
  <div id="sidebar">Ads</div>
  <div class="cleared">&nbsp;</div>
</div>

The CSS for those elements look as follows:

.cleared {
  clear:both;
  line-height:0;
}

There shouldn't be any doubt about what clear:both means by now, but what does line-height have to do with anything? We don't want these equalisers to take up any space, but if we specify them as empty elements they will be excluded in some browsers. Therefore we let them contain a &nbsp; and then we set the line height to zero.

Bugs, Bugs And More Bugs

If you've endured this far you probably realise by now that floating elements aren't exactly trivial. It should come as no surprise that even browsers have some problems with them. At least some browsers. We talk, of course, about Internet Explorer for Windows.

IE/Win has so many complicated float-related bugs that we can't go into it here. The example in this article doesn't work at all in IE/Win, but the article is too long anyway, without venturing into the jungle of bug fixing.

Fortunately, there is a simple solution that fixes many of the IE float bugs. We saw earlier that all floats become a block box. The standard says that the display property is to be ignored for floats, unless it's specified as none. If we set display:inline for a floating element, some of the IE/Win bugs disappears as if by magic. No one knows exactly why. IE/Win doesn't make the element into an inline box, but many of the bugs are fixed.

Other than that we happily refer you to the indispensable site Position Is Everything.


1. Posted by daveeee, 11 December 2004 at 14:11

Another great article, thanks; I'll pass the URI onto some CSS beginners I know.

One little point:

.clear should probably be .cleared for it to work.

daveeee


2. Posted by Tommy, 11 December 2004 at 18:20

Thanks for catching that typo. I was getting rather cross-eyed at the end there.


3. Posted by sirshannon, 11 December 2004 at 19:39

just wanted to thank you for this latest article. I just realized that I visit your site almost every time you post something because of links from sites I subscribe to. I am not subscribed to The Autistic Cuckoo and can skip the middlemen.


4. Posted by Henrik Bohman, 12 December 2004 at 11:45

Excellent article. There are A LOT of articles concerning this topic out on the web, but the problem is that most people explain the results of using floats. You've explained how they work and hence how to use them. Theory and execution, great. Site most definitely added among my bookmarks.


5. Posted by Dale, 12 December 2004 at 16:24

Nice article, though I feel it would have helped to show a few images to see the effect of what you were doing. I guess you omitted these due to space reasons? Or you assumed that the less lazy among us would copy the examples to try them out. :-))


6. Posted by Thufir, 12 December 2004 at 23:50

Hi,

thanks for the article. I have already used floats for several designs, but I was always a little bit puzzled about how they function.

Your article is very good, thanks! Bookmarked it.


7. Posted by Tommy Olsson, 13 December 2004 at 07:40

@Dale: I know this article needs illustrations. It probably should have been split into two or three parts, because it got way too long. I could also have linked to a couple of example pages. As it was, I was quite tired at the end (I post everything in two languages, remember), so I just put it up and hoped for the best. :)


8. Posted by Ben de Groot, 13 December 2004 at 11:10

Very nice article, especially the explanation of the theory!

One thing though: it is not necessary to add a semantically meaningless element to the markup! This can all be done with CSS, see the article at PIE.


9. Posted by Tommy Olsson, 13 December 2004 at 11:20

Ben, I know this, but it's not fully compatible cross-browser.


10. Posted by Charles Martin, 13 December 2004 at 15:47

Again, great job... enjoyed the article on relative vs absolute positioning and find this one just as useful. Keep em coming!


11. Posted by nabeel, 21 December 2004 at 05:37

I was trying so hard to get my floats right (no pun intended) in both IE and Mozilla at the same time. I had two columns contained in a div. I floated the main div to the left and defined its width, and gave the sidebar a margin in order to clear the main div's width. This worked in Mozilla, but not in IE for Windows. IE would run the sidebar div at the bottom of the floated main div. I tried several things, but all atempts were in vain. After reading your article I simply floated both divs againt eachother with float: left.

And it worked. Now I have two divs living side by side in peace and security. Do you think this technique can also be used to solve the Israeli-Palestinian conflict.


12. Posted by Tommy Olsson, 21 December 2004 at 07:06

LOL. When it comes to politics I suppose I would rather recommend float:right, but the priniciple is the same. :)


13. Posted by Kris, 21 December 2004 at 10:34

Here are some ancient float experiments of mine. It has 3-column layouts, but the content order was not a concern at that time.

http://www.xs4all.nl/~apple77/columns/


14. Posted by Matt Keogh, 21 December 2004 at 12:32

Thanks - this was most useful. Another great tutorial is Creating Liquid Layouts with Negative Margins by Ryan Brill.


15. Posted by Dustin F, 22 December 2004 at 23:54

Wow! I was always somewhat confused about floats, and being a beginning coder, I don't always understand everything. I've got some time for my redesign, and I think I'll put this primer to good use. Thanks!


16. Posted by scattermachine, 23 December 2004 at 04:12

Great explanation of the FLOAT. It's always nice to see why things behave as they do.

I found the link to this article in the Mezzoblue Dailies RSS feed and enjoyed it very much.

Thank you for the tips - I've bookmarked your site, and this article too. I know I'll rreference it for my future projects.

Now I can't wait to see the rest of your articles...


17. Posted by Ryan Oswald, 31 December 2004 at 01:29

I just want to be a designer. I don't care about XHTSS XSLMRSS PHPCP XMLST CSSATOM, just let me design! I want to be creative and design a site and manage it. I don't want my floats and absolutes to position unrelatively while I'm structuring my xhtml doctype cause I have to CHMOD my MovableType CMS for my blogging. So somebody please get this stuff working.


18. Posted by Tommy, 2 January 2005 at 16:03

@Ryan: This is a pet peeve of mine. The thing that is slowing down the progress of web standards the most right now is authoring tools.

Even the best of them often produce unsemantic garbage. I'm an engineer type, so I don't mind learning all the three-letter acronyms, but I do realise that others come from a different place. I, too, wish that there were good tools for the design-orientated so that they could focus on what they do best.


19. Posted by Gaz, 3 January 2005 at 12:21

I have been using floats for a little while now.

I cannot seem to over come this problem:

3 columns usings floats left:main:right

When viewing on a text-only browser, you want your main content to come first. How can you achive this with floats?


20. Posted by Dmitrii Dimandt aka Mamut, 3 January 2005 at 11:28

Wow. Another great one.

I'll have to read it a couple of times though before I finally understand it


21. Posted by Tommy Olsson, 3 January 2005 at 12:20

@Gaz: If you look at the example at the end of the article, you'll see an example of how this can be achieved. Basicly you need one or two wrapper divs.


22. Posted by Gaz, 3 January 2005 at 16:05

Hi Tommy,

The only problem with this is that the far right column would have to be larger than the main column to stop the text flowing into the right column.


23. Posted by Gaz, 3 January 2005 at 16:21

Ignore that,

Cool

Cheers Tommy


24. Posted by Scott Schiller, 3 January 2005 at 19:31

This is a great resource and reference alongside PIE; my only gripe would be, "where are the pretty pictures?" ;)


25. Posted by Tommy Olsson, 4 January 2005 at 07:16

On PIE ... ;)

(I know, but I'm not a graphics designer. I'll try to make it better this year.)


26. Posted by Tarwin Stroh-Spijer, 13 January 2005 at 04:25

Thanks for the extensive yet easy to read article. Your humour (in brackets - bracketed remarks) and funny H#s keep my interest up even when I feel like skipping sections.

I've been trying to get back into web design (after leaving at the onset of full-blown CSS) and this is one of the best articles I've read on positioning.

PS: This is also the first real example of <fieldset> and <legend> that I've seen. So thanks for that!


27. Posted by Big John, 14 February 2005 at 08:46

This page is making me seriously consider starting a blog! :)


28. Posted by Leandro Rodrigo Saad Cruz, 22 March 2005 at 07:00

Nice article. How did you define the styles on this page ?! I can't find any ref to any external css document !

Cheers !


29. Posted by Tommy Olsson, 22 March 2005 at 07:03

All styles are defined in my external style sheet. If you use a browser that supports XHTML, the style sheet is linked with a <?xml-stylesheet?> instruction in the XML prologue. For HTML-only browsers, it's in a normal <link> element in the <head>.


Comments are disabled, due to excessive spamming.

Don't blame me. Blame the morons who are destroying the web by spamming.


Sections