TJKDesign: Home Page

ez-css Putting the 'less' in table-less layouts. css-101 logo
Bookmark this article at these sites:

3 columns fluid layout

This article on A List Apart has been a great source of inspiration for me. After taking this solution for a "test drive", I decided to implement negative margins the "other way around".

I think the major advantage of this technique is that it uses fewer non-semantic elements and one less "float". It also seems to cure small issues not listed in the original ALA's demo:

  1. links inside the right column appear not to be clickable in Opera 6
  2. there are background painting problems in MSIE
  3. there is one structural hack missing from the markup that makes NN6 unable to clear the left column

This new solution to create a table-less fluid three-column layout appears to be free of:

  1. CSS hacks
  2. Structural hacks for clearing (see No Clearing)
  3. IE/Win Conditional Comments
  4. Cryptic CSS rules
  5. Lengthy Styles Sheets
  6. "Best viewed in..." statements (see Browser Support)

This page shows the basic technique, but I have created a more "sophisticated" design based on this solution; this is the CSS challenge that "got me started".

The Logic

The image below shows how things work.
As you can see, I am shifting #container to the left instead of the right side (the opposite of what's done in the ALA article), and the most important part is that I'm not "floating" #sidebar.

The logic in term of markup and CSS

The Markup

<body>
<div id="outer_wrapper">
<div id="wrapper">
<div id="header">
<h2>Header</h2>
<p>...</p>
</div><!-- /header -->
<div id="container">
<div id="left">
<h1>Left</h1>
<ol>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
</ol>
</div><!-- /left -->
<div id="main">
<h1>Main</h1>
<p>...</p>
</div><!-- /main -->
<!-- This is for NN6 -->
<div class="clearing">&nbsp;</div>
</div><!-- /container -->
<div id="sidebar">
<h1>Sidebar</h1>
<p>...</p>
</div><!-- /sidebar -->
<!-- This is for NN4 -->
<div class="clearing">&nbsp;</div>
<div id="footer">
<h2>Footer</h2>
<p>...</p>
</div><!-- /footer -->
</div><!-- /wrapper -->
</div><!-- /outer_wrapper -->
</body>

The CSS files

I am listing here only the rules related to layout.
Image names and paths are simplified

Sheet for modern browsers (how to import this sheet):

/* Copyright 2004 - 2006 - All Rights Reserved - Thierry Koblentz - www.TJKDesign.com */
#outer_wrapper {
/* because "min-width" is not supported by IE, these pages use a script from PVII */
min-width:740px;
/* this is to "minimize" an IE bug related to background painting, but because it creates a gap below the footer, the same declaration is also added to #footer */
width:100%;
/* faux-column technique, this is the left one */
background:#fff url(left.gif) repeat-y left
}
#wrapper {
/* faux-column technique, this is the right one */
background:url(right.gif) repeat-y right
}
#header {
border:1px solid #b0b0b0;
background:#b0b0b0;
/* this is to "give layout" to the element and fix some peek-a-boo bug in  IE (v6 sp2) */
width:100%;
/* the above declaration creates an horizontal scroll bar in IE, this is to get rid of it */
margin:0 -1px
}
#container {
float:left;
width:100%;
/* IE doubles the margins on floats, this takes care of the problem */
display:inline;
/* this is where Ryan Brill (author of the ALA's article) and I go in "opposite directions" */
margin-left:-200px
}
#left {
float:left;
width:150px;
/* IE doubles the margins on floats, this takes care of the problem */
display:inline;
margin-left:200px
}
#main {
/* the width from #left (150px) + the negative margin from #container (200px) */
margin-left:350px
}
/* good to know: if #sidebar is to be shorter than #main, then there is no need for this rule */
#sidebar {
/* this is to keep the content of #sidebar to the right of #main even if the content of "main is shorter */
padding-left:100%;
/* this is to "bring back" the #sidebar that has been moved out of the viewport because of the padding value */
margin-left:-200px
}
#sidebar p {
/* this is to make sure IE (v6 sp2) *displays* this element (same problem as #header, but using a different fix) */
position:relative
}
#footer {
/* see #outer_wrapper  */
width:100%;
/* this is to clear #container */
clear:both;
border-top:1px solid #b0b0b0;
border-bottom:1px solid #b0b0b0;
background:#b0b0b0}
/* this is the class that is applied to 2 structural hacks in the markup. The first "meaningless" element is used to clear #left in NN6 and the last one is used to clear #container in NN4 */
.clearing {height:0;clear:both}

As you can see, a few declarations in here are only used to "fix" MSIE/Win; if you decide to implement this technique, my advice is to remove these declarations from the Sheet to include them in a Conditional Comment.

Sheet for v4- browsers (how to import this sheet):

Because of NN4, it is important to use root relative paths to images in Styles Sheets.

Modern browsers ignore these styles because I am using a script to serve this Sheet to old browsers.

/* Copyright 2004 - 2006 - All Rights Reserved - Thierry Koblentz - www.TJKDesign.com */
#outer_wrapper {
/* faux column technique: this background image "contains" the left column */
background-image:url(/root relative path/outer_wrapper.gif);
background-repeat:repeat-y;
border:1px solid #b0b0b0
}
#header,#footer {
/* this is to  "force" a 100% value */
width:150%;
/* the background declaration is a trick to make NN4 paint the background color in the whole DIV, not just behind its content */
background:#b0b0b0 url(/root relative path/clear.gif)
}
#container {
/* this is to make sure NN4 doesn't paint a background image in this element */
background-image:none;
float:left;
width:auto;
/* both padding and margin are needed to leave room for #sidebar */
margin-right:160px;
padding-right:160px
}
#left {
float:left;
width:140px
}
#main {
/* with NN4, background declarations are very important when it comes to positioning elements. The layout breaks if NN4 doesn't have an image to paint in the  background of this element */
background-image:url(/root relative path/clear.gif);
/* this is to keep the wrapper inside the viewport */
margin:0
}
#sidebar {
/* this is the background color for #sidebar; I also make sure not to inherit any background image */
background:#ccc none;
margin:0;
padding:10px 0;
/* with "modern" browsers this element is not a float, but it has to be for NN4 */
float:right;
width:180px
}
/* this is the class that is applied to 2 structural hacks in the markup (see #2 and  #5) */
.clearing {clear:both}