Better than Holy Grail (how to make dynamic full width 1-3 column CSS layout)
Thursday, February 28, 2008 (15:39:46)

Posted by Madis

Introduction

Hello,
In this article I would like to explain how to make a CSS based tableless layout which features full width of screen(or any percentage) and main content column, which width simply depends whether side boxes exist or not (unlike Holy Grail). You can call it css-table, but I wouldn't.
Usually the content column (div) is given margin-left or margin-right value of side box. But I would like it to expand automatically, so that if I delete a side, or give it a CSS value of display: none, my main content will expand and all this must work correctly. There is one bug though, if there is some wide content in our main content box, the content box will go below our floated box.

I also clarify, that there is no javascript in this method.

This article is meant more for people who already know some CSS and might be useful for advanced CSSers aswell, but enough of the introduction, let's get to the business.
Tags: dynamic width center column, full width

The usual solution

Usually the code for three column layout looks like this:

Code:
<div class="container">
  <div class="left_side">Left side<br />Left side</div>
  <div class="right_side">Right side<br />Right side<br />Right side</div>
  <div class="center">Center content<br />Center content<br />Center content<br />Center content</div>
</div>

That is actually exactly that we will use aswell. We get to the difference soon.

The basic CSS would be something like this:
Code:
.container {
  width: 700px;
  color: #000;
}

.left_side {
  float: left;
  background-color: #C9CDEF;
  width: 160px;
}
.right_side {
  float: right;
  background-color: #F8C0B8;
  width: 160px;
}
.center {
  background-color: #F9FCD1;
}

Let's test it.
Example #1

As we can see the center column starts to continue below the left column after the left column is finished.
To avoid that the center column is commonly given sidemargins. Let's try adding
Code:
  margin-left: 160px;
  margin-right: 160px;
to .center

Example #2

It's all great. But the idea of the whole thing was to avoid these margins aswell, as it's much more comfortable to have it dynamic. So that center column expands itself to the sides if any of the sideblocks is missing.

Let's step back to the code of example #1.


My solution

For Internet Explorer 6, nothing else is required than "activating" the hasLayout for center column. This could be done for example giving it height:100%, or zoom: 1;
Just in case we give all the elements height:100%, who knows what IE6 likes.

Now, for the normal browsers, we are still where we were in example #1.
The solution is simple. We give all the columns display: table;

Example #3

Hey! What's that? The center column is only as wide as is the content in non-Internet Explorer 6 browsers.

Don't worry, there's a fix for that too. We just make fictional content that we won't show but as it does still exist browsers will render the column with the right width.

First we need to add a new element before the center column ends
Code:
<div class="widthfixer"></div>

As there's a lot of text and IE6 doesn't need it we use the @import function, thus IE6 doesn't understand this (nor does it understand :after and content: "").

And this is what the imported css file will contain:

Code:
/*This will make content 100% wide without disturbing side float*/
.widthfixer:after {
  content: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut odio nisl, tempus et, pretium ut, iaculis ut, ipsum. Maecenas et mauris at orci lacinia porttitor. Mauris gravida sapien quis metus. Quisque venenatis, tortor id venenatis interdum, leo augue cursus mi, sed imperdiet neque lectus vel urna. Pellentesque congue enim ut turpis. Nullam posuere lorem laoreet augue. Integer fermentum augue vel enim. Nulla ultricies felis. Integer dignissim, justo vel aliquam fermentum, magna eros hendrerit ante, elementum fermentum magna libero tempus nunc. Maecenas dignissim, ipsum id tincidunt porta, arcu purus vehicula leo, ac lacinia tellus purus non lacus. Ut blandit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In ut lacus eget felis ultricies pharetra. Fusce cursus, augue vitae laoreet viverra, odio purus laoreet ipsum, eget semper pede risus quis ligula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In sagittis arcu quis eros. Praesent placerat lacus id mi. Aliquam erat volutpat.";
  visibility: hidden;
  display: block;
  height: 0;
  overflow: hidden;
  margin: 0;
  padding: 0;
  font-size: 10px;
}

Check it out now:
Example #4


Columns to same height

The only thing left, you might want, is to make all the columns the same height. There is a hacky solution for that too. If you're not using any full height backgrounds for the side columns, then don't use this, but anyway...

We need to add a very long bottom padding to each column and then remove it with same high negative margin. Like that:
Code:
padding-bottom: 20000px;
margin-bottom: -20000px;

Also add overflow:hidden for the container.
So here is the final solution.

Example #5

And this is the code:

XHTML:
Code:
<div class="container">
  <div class="left_side">Left side<br />Left side</div>
  <div class="right_side">Right side<br />Right side<br />Right side</div>
  <div class="center">
    Center content<br />Center content<br />Center content<br />Center content
    <div class="widthfixer"></div>
  </div>
</div>


CSS:
Code:
@import url('hack.css');

.container {
  width: 700px;
  height: 100%;
  overflow: hidden;
  color: #000;
}

.left_side {
  float: left;
  background-color: #C9CDEF;
  width: 160px;
}
.right_side {
  float: right;
  background-color: #F8C0B8;
  width: 160px;
}
.center {
  background-color: #F9FCD1;
}

.left_side, .right_side, .center {
  display: table;
  height: 100%;
  padding-bottom: 20000px;
  margin-bottom: -20000px;
}

Why did I need to publish this article? Because I've seen no-one else using the widthfixer and display: table approach, which should make this one original.

Independent Thought
Of the 70-528 series, the easiest one is 70-536. However to go for advanced courses, doing 70-290 is essential.

techtrek blog

Content received from: Dragonfly Eesti, http://000.pri.ee