CSS

Centered, framed layout

Recently I come up with one interesting layout, which proved quite useful. I needed to simulate good old frames, but using CSS over semantic markup. Basic goals:

I looked at excellent resources about CSS frames and centered and/or fixed positioning, all available on the net, but none really suited my needs. Either lacking or way too complicated. So, here is mine - centered framed layout.

I tested it and it works in NN7.1, Firefox 0.9, Camino 0.8, WinIE 5.01+, Opera 7.51, Safari 1.2. I tested it and it fails in IE5/Mac (horribly) and Opera 6 (less horrible). Both can be circumvented, but I don’t need that. So, let me indulge myself and explain how it works…

Modern browsers

My layout needed two columns - left would be scrollable (#content), and right would be navigation, fixed (#nav). Those columns are both enclosed by parent div (#horizon) which will define the “frameset” size. Footer is the last piece.

<div id="horizon">

<div id="content">
...
</div><!-- content -->

<div id="nav">
...
</div><!-- nav -->

</div><!-- horizon -->

<p id="footer">(C) APLUS, 2004.</p>

First, I need a frameset. It will be 90% wide and 90% high, with 5% margin on all sides. This is done surprisingly easy (border is there purely to visually show the frameset).

#horizon {
	position: absolute;
	width: 90%;
	height: 90%;
	top: 5%;
	left: 5%;
	overflow: hidden;
	display: block;
	border: 1px solid #000;
}

Then comes the main, content column. The hardest thing here is to define how wide you want it to be. Really. To take care of scrolling, just add proper overflow.

#content {
	position: absolute;
	width: 80%;
	height: 100%;
	top: 0;
	left: 0;
	overflow: auto;
}

Navigation column is almost the same, only I align it to the right edge.

#nav {
	position: absolute;
	width: 20%;
	height: 100%;
	top: 0;
	right: 0;
}

You can easily add more columns. Since all of this is absolutely positioned, just use proper width and left/right and/or height and top/bottom combinations. This simple thing was all I needed.

Last is the footer, which should be located at the bottom.

#footer {
	margin: 0;
	position: absolute;
	bottom: 0;
	left: 0;
	width: 100%;
	height: 1.5em;
	display: block;
}

And that is all for good, modern browsers. Now let’s take care of the PoC…

Win IE

The layout above is totally broken in WinIE, because it ignores the height. Luckily, it does properly move the frameset to 5% of the top and left edge (IE5/Mac doesn’t even do that).

So we need to compensate the height. First, use conditional comments to make this visible only to IE6 and below.

<!--[if lte IE 6]>
<style type="text/css" media="screen, projection, tv">

</style>
<![endif]-->

Then, step by step, fix the heights, using proprietary expression property.

First in the queue is frameset. We need to grab view port’s height and multiply it by 0.9 (90%). In IE5.x, we use document.body.clientHeight which returns proper value. Although this property exists in IE6, it returns 0, so we need to use document.documentElement.clientHeight instead.

#horizon {
	height: expression(
		(
		document.body.clientHeight) ?
			document.body.clientHeight * 0.9 + 'px'
		:
			document.documentElement.clientHeight * 0.9 + 'px'
		);
}

The hardest part is over. Now that frameset has needed height, all we have to do is to fetch it and apply it to each column. Again, this can easily be customized for more columns/rows, borders, margins etc.

#nav {
	height: expression( document.all.horizon.offsetHeight + 'px' );
}

#content {
	height: expression( document.all.horizon.offsetHeight + 'px' );
}

That’s it. Take a look at prettier example, or build your own. Like everything else on this site, the layout is CC licensed, so take your best shoot at it.