Faux Columns :: The Next Generation
When the Faux Columns Article on A List Apart first came out in 2004 it was pretty sweet information for a lot of us. Finally we were able to make our two- and three- column layouts look like those columns actually extended the entire height of the page, no matter what the height of their actual content.
Now I want to show you how to take that a bit further. Inspired by my work (in progress) of redesigning/recoding the Zend.com site, I will show you how I accomplished rounded, stacked columns (six of them in this case) with “more” links that all sit in the same spot relative to the bottom of their columns, as in this layout.
For this tutorial I am going to use a simplified version of the layout.
The Basic Page Structure
First we put the entire body of the page in a containing div and give it an id of “container.”
:c:
Here are the general styles we will start with.http://manisheriar.com/blog/wp-admin/post.php?action=edit&post=13
Sheriar Designs › Edit — WordPress First we reset the global margin and padding to default to 0. Next we apply our horizontal jump fix, give the body a background color and font stylings, declare our basic link styles, and creat a span class called “clear” for use in clearing our floats when necessary. I like to use this method of clearing floats (when overflow:auto) doesn’t seem to work because it is relatively little markup, has no effects on unstyled documents, and doesn’t require a lot of fancy css hacks. Make sure to specify the line-height, font-size, and height all to be 1px high and then give it a top margin of -1px – making your span totally “invisible” even though it has been declared as a block-level element. Finally we define the size, position, and stylings of our container div.
* {
margin:0;
padding:0;
}
html {
min-height:100%;
margin-bottom:1px;
}
body {
background:#eee;
position:relative;
font-family:Verdana, Arial, Helvetica, sans-serif;
font-size:11px;
color:#333;
}
a img {
border:none;
}
a {
text-decoration:none;
}
span.clear {
display:block;
height:1px;
line-height:1px;
font-size:1px;
margin-top:-1px;
clear:both;
}
#container {
position:relative;
width:780px;
margin:5px auto;
padding:7px 0 0 0;
border:1px solid #ccc;
background:#fff;
}
The Wrapper Divs
Ok, so we want to display to rows of three boxes – two wide and one narrow – and we want them all to end at the same place regardless of content length, and they all have rounded corners. Instead of giving corners and borders to each box individually, I’m going to give corners and border to the entire row of boxes.
The Images
To accomplish this we need three wrapper divs: One to give the top rouned borders, one to give the side borders, and one to give the bottom rounded borders. When lined up yet viewed separately they will look basically like this (the top row has a grey background in the “columns” rather than white because the heading that follows will have a grey background):



The Structural Code
:x:
Each row of three boxes is wrapped in the three wrapping divs (box_wrap1, box_wrap2, and box_wrap3). Each box itself is wrapped in in a div with the class of “box” and an additional class of either “wide” or “narrow” and a unique id.
<div class="box_wrap1"><div class="box_wrap2"><div class="box_wrap3">
<div class="box wide" id="box1">
BOX 1 CONTENT
</div>
<div class="box wide" id="box2">
BOX 2 CONTENT
</div>
<div class="box narrow" id="box3">
BOX 3 CONTENT
</div>
</div></div></div>
<div class="box_wrap1"><div class="box_wrap2"><div class="box_wrap3">
<div class="box wide" id="box4">
BOX 4 CONTENT
</div>
<div class="box wide" id="box5">
BOX 25 CONTENT
</div>
<div class="box narrow" id="box6">
BOX 6 CONTENT
</div>
</div></div></div>
:c:
Box_wrap1 is the outer wrapper and will display the top image for the faux columns. It is givien a top padding of 3px to make space for this image. It is given a bottom margin of 7px to add the desired space between top and bottom rows of boxes and the bottom row of boxes and the bottom of the container.
.box_wrap1 {
padding-top:3px;
background:url(images/bg_box_top.gif) no-repeat top left;
margin-bottom:7px;
}
Box_wrap2 will display our bottom image for the faux columns and assigns 2 pixels of bottom padding to allow space for that image.
.box_wrap2 {
padding-bottom:2px;
background:url(images/bg_box_bottom.gif) no-repeat bottom left;
}
Box_wrap3 is the final wrapper and it will expand with the box content and therefor display the side borders. It is given 7 pixels of left margin to move the image and text into place. It is also given a position of relative so that we can later position the “more” links absolutely within it (for a fantastic article on positioning see Relatively Absolute). Finally, it is given a height of 1% to fix an IE float bug (whenever IE is misbehaving with floats try applying this fix to the float container).
.box_wrap3 {
position:relative;
background:url(images/bg_box_center.gif) repeat-y left;
margin-left:7px;
height:1%;
}
Each box is floated left, wide and narrow boxes are each given the appropriate widths, and wide boxes are given a right margin of 7 pixels (narrow boxes don’t require this margin since they are the last boxes in the row).
.box {
float:left;
}
.box.wide { /* for wider left two boxes */
width:280px;
margin-right:7px;
}
.box.narrow { /* for narrower right box */
width:190px;
}
The Content Code
:x:
After the main heading in each box we have an additional div called “content.” This is to give appropriate padding around all content within the boxes. The reason we didn’t simply apply this padding to the box itself is so that the heading and its background shading could lie flush against the edge of the box. I tried putting the padding on the box and using negative margins on the heading but with varying results. The other thing of interest here is that each first paragraph is given a class of “first” which will be explained in the CSS section.
<div class="box" id="box#">
<h1>HEADING »</h1>
<div class="content">
<p class="first">FIRST PARAGRAPH</p>
<p>REMAINING PARAGRAPHS</p>
<p class="more">» More</p>
</div>
</div>
:c:
First I’ve defined basic link styles. For the heading I define the font styles, give a background color, move it over from the left by 1 pixel so that it doesn’t cover the border, which is actually a background image (I later remove this 1 pixel shift for the narrow boxes because they don’t end up needing it due to their placement), then I define the heading link with a display of block so that I can apply padding to it, which I do to fill out the background a bit.
.box a {
color:#005fa9;
}
.box a:hover {
color:#ff9c00;
}
.box h1 {
font-size:13px;
margin-left:1px;
background:#ecece5;
text-transform:uppercase;
}
.box.wide h1 {
width:277px;
}
.box.wide#box1 h1,
.box.wide#box4 h1{
width:278px;
}
.box.narrow h1 {
width:190px;
margin-left:0;
}
.box h1 a {
display:block;
font-size:13px;
line-height:22px;
padding:0 7px 2px 7px;
}
Next I define the content div, which contains everything but the header. I give it padding of 12 pixels top right and left, and padding of 24 pixels for the bottom. This additional bottom padding creates room for our absolutely positioned “more” links.
.box .content {
padding:12px;
padding-bottom:24px;
}
Then I give all paragraphs a top and bottom margin of 12 pixels and also define a class of “first” which can be given to the first paragraphs in each box so that there is not a large space above them (their margin combined with the top padding of the content div). You might ask why I didn’t just give a top padding of 0 to the content div? The answer is that a real layout, rather than this demonstration one, will need a lot more flexibility – it won’t always be a paragraph at the top of the content div; it might be an image, a list, another div, or something else. If we gave no padding to the top of the content div we would still need to create a class of “first” to give a top margin to those elements that might appear first but do not already have top margins defined.
.box p {
margin:12px 0;
}
.box .first { /* give to any element that requires no space above */
margin-top:0;
padding-top:0;
}
Finally I absolutely position the paragraph that contains the “more” links. I give it a bottom value of -4 pixels (which, because paragraphs are set to have 12 pixes of margin top and bottom, ends up bringing the text up about 8 pixels from where they would sit at the bottom), bring it over from the right 21 pixels, and assign font size and weight values. IE was doing a weird thing wrapping the link so that the text was above the arrow – a width of 100% on the paragraph fixed that.
Remember that we gave each box_wrap3 div a position of relative so now anything positioned absolutely within it will be positioned relative to its borders. So now we have to give different right values to each column-set of boxes (1 and 4, 2 and 5, 3 and 6) so that the links sit horizontally in the correct place. You may wonder why we didn’t set the relative position on each box, instead of the wrapper, so that each link would automatically sit in the right space horizontally without having to feed different values in for each set? The answer is this: if we did that, each “more” link would line up at the bottom of the content of each box, instead of at the visual bottom that is created by the wrapper divs.
.box p.more { /* Absolutely positions all links to bottom right of boxes */
position:absolute;
bottom:-4px;
right:21px;
text-align:right;
width:100%;
font-size:10px;
font-weight:bold;
}
.box#box1 p.more,
.box#box4 p.more {
right:506px;
}
.box#box2 p.more,
.box#box5 p.more {
right:222px;
}
That’s a Wrap!
Once again you can view the completed page to see how this all comes together.
Hopefully this tutorial has been helpful. I could have simplified it somewhat, but I wanted to base it off of a real-life example. Variations of this method can be used in all sorts of css layouts where the client or the designer require that boxes or columns always visually end at the same spot regardless of content. I know this comes up for me all the time!
November 6th, 2005 at 9:13 pm
You may also be interested in this article that appeared a couple of weeks ago. Titled In search of the One True Layout it shows, among other things, how to make all columns appear to be the same height. But without the need for faux column style background images.
None of your lovely rounded corners, though! Thanks for the insight.
Enjoy. David.
May 3rd, 2006 at 5:05 pm
I love it. I am, however, experiencing a problem with the “more” links in boxes 1, 2, 4 and 5 in my Firefox 1.5 browser. Those links are not clickable.
My hunch is that the width of 100% is the cause of this, but I have no testing to back up my claim other than the fact that everything works in IE. If this is the case, might a set width of X pixels accomplish the same thing?
May 4th, 2006 at 8:48 am
Andy: Thanks for pointing that out. I see that too. I made this pre-1.5 and it worked great in FF then. Interesting …
December 20th, 2006 at 10:30 pm
I happened to revisit this post today and got curious about those non-clickable links. Took a look at the code and realized that that paragraphs holding the links were absolutely positioned, and therefore were spanning the entire width of the page, and sitting on top of each other. I gave the link-holding paragraphs on the left a z-index of 3, and the ones in the middle one of 2 … that seems to have solved it. ;)
October 22nd, 2007 at 1:50 pm
I want to know if it is possibile to have a box liquid, so to cover all the page. And the container width 98%.
November 6th, 2007 at 5:22 pm
Carletto:
I think a flexible layout could work if you did away with the rounded corners and just used background colors and borders to delineate the boxes.