Holy Grail 3 column layout without using float

Yes. You read the post title correctly. It is not a mistake. The technique outlined below exists, and it’s cross-browser compatible (with the obligatory tweak or two for our dear friend Internet Explorer, of course). No more pesky clearing of floats. It’s CSS layout nirvana. And it’s here today.

First, the markup (borrowed from here)


content

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus varius eleifend.

Donec euismod. Praesent mauris mi, adipiscing non, mollis eget, adipiscing ac, erat. Integer nonummy mauris sit.

Strictly speaking, the wrapper div isn’t needed, except in my example outlined below, I’m using a modified version of the Man In Blue’s excellent FooterStickAlt to ensure a full-page layout, even with the smallest amount of content. It’s also a handy element to have around should you wish to use a full-length background to ensure the appearance of equal height columns with varying content height.

Now normally, the next step would be to float the sidebars and the center column, right? And then clear the float on the container div, right? No sirree, we’re going to be using the oft-overlooked display: inline-block which, ever since Firefox 3 was released, became a viable option for site layout. But I suppose front-end developers have gotten used to using floats to achieve multi-column layouts, even though it’s not really the right tool for the job. If you think about it, floats are really for image elements and pull quotes, designed to have text “float” around it.

The W3C defines an inline-block element as an element that behaves like a block element when it comes to padding, borders and margin, and its descendant elements all see it as such but behaves like an inline element to its sibling and ancestor elements. Neato.

Let’s start off slowly with our CSS:

body {
	width: 960px;
	margin: 0 auto;
}
#header, #footer {
	background: orange;
}
#content, .sidebar {
	display: inline-block;
	vertical-align: top;
}
#content {
	background: pink;
	width: 60%;
}
.sidebar {
	background: yellow;
	width: 20%;
}
#footer {
	background: blue;
	color: #FFF;
}

Of course, no self respecting CSS technique would exist if it didn’t break IE in some way or another, so without further ado, here is what’s needed to get Redmond’s browser to behave:

* html #header, * html #footer {
	height: 7.5em;
}
#content, .sidebar {
	display: inline;
	zoom: 1;
}

If you are super keen to try out this technique and you’ve copied & pasted the above code and run it in your browser, you’re probably wondering why the elements aren’t lining up neatly like they should. And rightly so. That is because inline elements are affected by white space within the HTML document. And therein lies the rub.

But all is not lost. There are basically two approaches to solving this… “fixing” the HTML by removing the white space between the inline-block elements, or adding a smidgeon of additional CSS to achieve the same effect. Admittedly here I wasn’t the one who invented this method – I found it here and decided to try and see if instead of only using it for image galleries and horizontally centred navigation, it could be used for laying out an entire page.

Basically, what we’re going to be doing, is removing white space in our parent element (in this case, #container) and putting it back in each of the child elements (each of the elements that have display set to inline-block). A little bit of experimentation led me to see that most browsers will be happy with eliminating word-spacing, but Webkit-based browsers (essentially Safari and Chrome) needed to have letter-spacing removed instead.

#container {
	word-spacing: -4px; /* IE, Firefox, Opera */
	letter-spacing: -4px; /* Webkit */
}
#content, .sidebar {
	word-spacing: normal; /* IE, Firefox, Opera */
	letter-spacing: normal; /* Webkit */
}

At this point, everything should be working quite nicely. You can stop at this point, and have a fully working layout.

Adding the sticky footer is an added bonus. Here’s what you’ll need:

html, body {
	height: 100%;
}
html {
	background: green;
}
body {
	width: 960px;
	margin: 0 auto;
}
#container {
	word-spacing: -4px; /* IE, Firefox, Opera */
	letter-spacing: -4px; /* Webkit */
}
#content, .sidebar {
	word-spacing: normal; /* IE, Firefox, Opera */
	letter-spacing: normal; /* Webkit */
}
#header, #footer {
	min-height: 7.5em;
	background: orange;
	width: 100%;
}
#content, .sidebar {
	display: inline-block;
	vertical-align: top;
	padding: 9em 0;
}
#content {
	background: pink;
	width: 60%;
}
.sidebar {
	background: yellow;
	width: 20%;
}
#header {
	margin-bottom: -7.5em;
	position: relative;
	z-index: 10;
}
#container {
	position: relative;
	z-index: 0;
	min-height: 100%;
}
#footer {
	background: blue;
	color: #FFF;
	margin-top: -7.5em;
}

And add this in your IE CSS for IE 6 (because it doesn’t understand min-height, and instead interprets height to behave like min-height):

* html #container {
	height: 100%;
}

And that should be that. Comments welcome.

Posted in Tutorials

Leave a Reply

Your email address will not be published. Required fields are marked *

*