Three-Column Layouts with Float and ClearThe next demo uses five visual elements: a header, three columns, and a footer. This demo is about as simple as it can be, but the structure it demonstrates can be the foundation of complex and beautifully designed pages. The page you create is going to be only 450 pixels wide, with three columnseach 150 pixels across. The objective is to float the three columns side by side under the header and then have the footer run across the bottom. The footer will be the width of the page, and will sit directly under whichever of the three columns is longest. The first step, as always, is to write the markup <body> <div id="header">This is the header</div> <div id="contentarea"> <div id="column1">These divs will float side by side to create columns. This is div 1 with a little text to give it some height...</div> <div id="column2">This is div 2 with a little less text so it's a different height than the other two...</div> <div id="column3">The objective is that no matter which of the three divs is longest, the footer sits below it...</div> </div><!--end contentarea--> <div id="footer">This is the footer</div> </body> Then you start with some simple styles to color the backgrounds of the elements so you can see their positions (Figure 5.13). Here are the styles div#header {width:450px; background-color:#CAF;} div#contentarea {width:450px; background-color:#CCC;} div#column1 {width:150px; background-color:#FCC;} div#column2 {width:150px; background-color:#CFC;} div#column3 {width:150px; background-color:#AAF;} div#footer {width:450px; background-color:#FAC;} Figure 5.13. This shows the basic markup with each div a different color.
I added one extra structural element to the markupa div that contains the three column divs, called contentarea. The purpose of this element is to enclose the three columns so that as any of the columns get longer, the bottom of this container gets pushed down, and the footer that follows gets pushed down too. Without it, the footer moves up as close as possible to the header. Now, while you can see that this "wrapper" div surrounds the three columns in the markup, this is not what is happening in the browser. The CSS recommendations do not require a div to enclose floated elements, but by using clear, you can make it do just that and thereby get your footer to position correctly below the longest column. Let's start by floating the three columns, which pushes each one up and to the left as far as possible. Here, I've set it up so that there is room for the columns to still be side by side (Figure 5.14). Here's the CSS div#header {width:450px; background-color:#CAF;} div#contentarea {width:450px; background-color:#CCC; border:solid;} div#column1 {width:150px; background-color:#FCC; float:left;} div#column2 {width:150px; background-color:#CFC; float:left;} div#column3 {width:150px; background-color:#AAF; float:left;} div#footer {width:450px; background-color:#FAC;} Figure 5.14. The footer tries to move up. The containing div does not "contain" anything yet.You can see that the footer, in its effort to move up against the container div, is jammed up under the second, shortest column. I also turned on the border of the div#contentarea so you can see it. The top and bottom edge of the div touch, forming a solid black rectangle. You can see three sides of this rectangle because those sides add to the width of the div. The bottom edge of the box is obscured by the three columns. The div has no vertical height because it contains only floated elements and, therefore, behaves as if it is empty. But that's not what you want; you have to devise some way to make that div's box open up and surround the columns.
The way to do this (until I show you the really good, but more complex, way to do it in "The Alsett Clearing Method" later in the chapter) is to add a non-floated element into the markup after the column divs and then force the containing div to clear it. This opens the div up to the height of the tallest column. To do this, you add an extra div into the markup as shown here <div id="contentarea"> <div id="column1">These divs will float side by side to create columns. This is div 1 with a little text to give it some height...</div> <div id="column2">This is div 2 with a little more text so it's a different height than the other two...</div> <div id="column3">The objective is that no matter which of the three divs is longest, the footer sits below it...</div> <div class="clearfloats"><!-- --></div> </div><!--end contentarea--> <div id="footer">This is the footer</div>
Notice that this new element is positioned after the floated columns but before the container div closes and that it has the class "clearfloats". Now you need to add a style for this class
div#header {width:450px; background-color:#CAF;}
div#contentarea {width:450px; background-color:#CCC; border:solid;}
div#column1 {width:150px; background-color:#FCC; float:left;}
div#column2 {width:150px; background-color:#CFC; float:left;}
div#column3 {width:150px; background-color:#AAF; float:left;}
div#footer {width:450px; background-color:#FAC;}
div.clearfloats {clear:both;}
Now the contentarea div is forced to enclose the columns so it can clear the non-floated element, and the footer, which follows the container in the flow, is positioned correctly beneath the columns (Figure 5.15). Just to show you that the footer is always below the longest column, I'll add some text to the center column to make it the longest one. I'll also turn off the border of the container div now that you know it's doing its job (Figure 5.16 on the next page). Figure 5.16. The footer always appears below the longest column.Because I added this extra markup purely to achieve a presentational effect, it's not ideal in terms of keeping this markup structural, but it's a simple way to get the result I want and its relatively simple to understand. Now that you get the idea of how this works, let's look at a more complex, all-CSS method for enclosing floats that requires no additional elements in the markup. The Alsett Clearing MethodNamed after its creator, Tony Alsett (www.csscreator.com), the Alsett Clearing Method uses the CSS :after pseudo-class to insert a hidden bit of non-floated content (instead of a div) at the appropriate place in the markup. The clear is then applied to this non-floated content.
:after enables you to define a string of characters to be inserted after the content of an element. You set up the required CSS as a class and then add the class to the containing element. Here's the complete page markup for this demo; in this markup, I'm using the Alsett method to force the div to enclose the floated elements. You can see the results in Figure 5.17. Figure 5.17. There's not much visual difference between this page and Figure 5.16, but here the clearing is achieved with the Alsett method.Here's how it works <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>Clearing floats demo</title> <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" /> <meta http-equiv="Content-Language" content="en-us" /> <style type="text/css"> body {margin:0px; padding:0px; font: 1.0em verdana, arial, sans-serif;} div#header {width:450px; background-color:#CAF;} div#contentarea {width:450px; background-color:#CCC;} div#column1 {width:150px; background-color:#FCC; float:left;} div#column2 {width:150px; background-color:#CFC; float:left;} div#column3 {width:150px; background-color:#AAF; float:left;} div#footer {width:450px; background-color:#FAC;} .clearfix:after { <-- a content: "."; <-- b display: block; <-- c height: 0; <-- d clear: both; <-- e visibility: hidden; } .clearfix {display: inline-block;} <-- f * html .clearfix {height: 1%;} <-- 6 .clearfix {display: block;} <-- 6 </style> </head> <body> <div id="header">This is the header</div> <div id="contentarea" class="clearfix"> <div id="column1">These divs will float side by side to create columns. This is div 1 with a little text to give it some height...</div> <div id="column2">This is div 2 with a little more text so it's a different height than the other two...adding a little more text here makes now this column the longest.</div> <div id="column3">This version uses the Alsett clearing method which uses the CSS :after psuedo-class to add content and force the container to enclose the floats, and only requires a class to be added to the markup, instead of a "clearing" element.</div> </div><!--end contentarea--> <div id="footer">This is the footer</div> </body> </html>
Using comments in this code, I provided a superficial explanation of this method; if you want to learn all about the whys and wherefores of how this method actually works, go to Big John and Holly "Hack" Bergevin's site, Position Is Everything (www.positioniseverything.net). Here you'll also find lots of great information on floats in general. What's good about this method is that you don't need to know how it works to use it. You can just paste the styles into your style sheet and add the class to any element that you want to enclose floats; using it is simple. A couple of observations, though. First, in Internet Explorer for Windows, divs will enclose floats without any clearing even though this is not correct behavior. As a result, when working with floated elements you shouldn't assume that what you see in Internet Explorer works everywhere. If you want a container to enclose floats, use one of these two methods demonstrated above to ensure cross-browser clearing. Second, Internet Explorer has some buggy behaviors having to do with floats such as the guillotine bug, which can cut off the bottom of elements that contain both links and floats (this Internet Explorer bug and others are well documented at Position Is Everything). The version of the Alsett method used here addresses these Internet Explorer float bugsanother reason it's superior to the "clearing div" method I showed you first. You can strip the Alsett clearing code down to the highlighted lines in the markup above, but note that two of the lines of comments (highlighted) are also part of an Internet Explorer hack to fix the guillotine bug, so you must keep them in your CSS. |