Monday, January 4, 2010

Three-Column Layouts with Float and Clear








Three-Column Layouts with Float and Clear


The 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


[View full width]

<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.




About Footers


A footer is like a header, but it runs across the bottom of the page rather than the top, and it often contains a second set of major navigation links as well as some minor links such as a link to a privacy policy or a link to the site's terms of use and copyright information. Also, if the viewer has scrolled to the bottom of a long page, the footer links can provide main-choice options so the viewer doesn't have to scroll back to the top again.


You can add a footer to the designs you've seen earlier in this chapter in the same way you added the header. However, if the absolutely positioned columns happen to be longer than the content area (which, being in the document flow, pushes the footer downward), the columns will extend over the footer. What you need, and will create, is a page structure where the bottom of the longest column, whichever one it happens to be, sets the position for the top of the footer.



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.


Contrary to the CSS specification, in Internet Explorer for Windows, the div does surround the float, so it already shows the result displayed in Figure 5.15, but this does not happen in other more standards-compliant browsers. Be sure to clear the wrapper as described, or your layout will only work in Internet Explorer. This is just another reason why it is important to develop in a standards-compliant browser and then adjust for Internet Explorer afterward.

Figure 5.15. The containing element is forced to enclose the non-floating div, thus forming a boundary below the columns that the footer cannot move above.




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


[View full width]

<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>


Divs don't like to be empty. If you don't have any content for a div, simply put a comment inside it. Some people put a period or a similar small element in these "clearing" elements and then add a couple of extra rules to set the line-height and height of the div to zero so that content is not visible. The important thing is not to have this extra element take up space in your page. Sometimes you have to experiment to achieve that.



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


The clearing div has a class in the code above and the reason it has a class is because you might want to use it multiple times on the page. (IDs can only be used once per page). Note also that although there are only left floating elements, I used clear:both instead of clear:left in case I also want to clear right-floated elements elsewhere on this fictional page.




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 Method


Named 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.


This is a superior method of clearing floats to the "clearing div" method in the previous example since it requires no additional markup.



: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



[View full width]

<!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>


(a)The period is the last thing before the div closes

(b)Inline elements don't respond to the clear property

(c)Ensure the period is not visible

(d)Make the container clear the period

(e)Further ensures the period is not visible

(f)A fix for IE Mac

(6)The Holly hack for a bug in IE6 for Windows

(6)


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.








    No comments: