Faux Columns 2011

I have three divs floated left to make three columns. Each column has a background image which creates a border between them.

Unfortunately, the background image tiles only as long as the column/div and I need each div’s border to tile all the way to the bottom of the page - then length of the longest div.

The old way to fix this was "faux columns, using the tiling background on the containing element so that it only appeared that the background image was being applied to its column.

There’s got to be a better way to do this now, without wrapping divs. Is there?

I would normally wrap three floated divs in a parent anyway so I don’t see that the extra div is a worry for such a simple solution.

For IE8+ you could use the display-table-cell properties to make the columns equal but then they won’t wrap of course but I guess that’s what you want.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
html, body {
	margin:0;
	padding:0;
	height:100%;
}
.outer{
	display:table;
	height:100%;
	width:100%;
}
.col {
	display:table-cell;
	width:33%;
	background:red;
	height:100%;
}
.col + .col {background:blue}
.col + .col +.col {background:green}
</style>
</head>
<body>
<div class="outer">
	<div class="col">test</div>
	<div class="col">test</div>
	<div class="col">test</div>
</div>
</body>
</html>

They still need a parent wrapper anyway.:slight_smile:

It just feels a little dirty to be putting the background for all three divs in the parent div. But I’m thinking that’s what I’ll have to do.

I’ll experiment with the display-table-cell properties. At first I wasn’t interested because it has to work in IE7 and I didn’t want to have to write that many IE7-specific styles. But it just dawned on me that the background image is pretty subtle and if IE7 doesn’t display it, that’s totally fine. So… I will def try the display-table-cell.

Thanks!

I’m curious to hear other opinions on this too if there are any more out there.

Equal columns have been my speciality since early 2003 and I have tried literally thousands of different ways.:slight_smile: Almost all “hacky” methods require additional elements to make the thing work and even non hacky display:table methods require the extra wrapper. CSS3 does offer some interesting possibilities but isn’t ready for mainstream yet.

As I said anyway if you have three floats you are going to need a parent to ensure that content under the float is cleared and that the floats are contained. Otherwise you run the risk of floats snagging or elements underneath not clearing properly. The most robust way is to use a parent to contain the floats. Indeed if you want equal columns then you need something that is a high as all the columns and the only element that will be as high as all columns will be a wrapper for all three columns. There is just no way of getting away from it.

How you make the columns can vary and you can use faux columns, or wide borders, or negative margins or absolute overlays, or multiple nested containers, or display:table as already mentioned. All depend on layout and circumstance as to which is best.

As you have already stated that you are using images for the background then it would seem that faux column approach would be the simplest. Of course if you have a fluid width layout then you may need a different approach as you can’t tile in the same way as a fixed layout.

Maybe if you had a picture of your design and its dynamics then we could offer more specific advice.

There is also a useful round up of equal column techniques here although the older ones are somewhat based on my original techniques (absolute overlays and negative margins (which were based on Doug Livingstone’s original and first equal column back in 2002)).

Here’s a quick example of a 3-column layout that doesn’t use css tables. It does have some of the faults that Paul mentioned, but it could probably be made to work in IE7 (just use classes in place of child and sibling selectors, and divs in place of generated content).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Equal Height Columns</title>
<style type="text/css">
	html,
	body {
		height: 100%;
		margin: 0;
	}

	.threecol {
		width: 100%;
		min-height: 100%;
		overflow: hidden;
	}

	.threecol > div {
		float: left;
		width: 30%;
		margin-left: 2.5%;
		vertical-align: top;
	}

	.threecol > div:before {
		content: "";
		display: block;
		height: 999999px;
		margin-bottom: -999999px;
		border: 1px solid black;
		background-color: lightblue;
	}

	.threecol > div > div {
		padding: 0 4px 0 4px;
	}

	.threecol + div,
	.threecol + div + div,
	.threecol + div + div + div {
		position: relative;
		float: left;
		width: 30%;
		margin-left: 2.5%;
		border-bottom: 1px solid black;
	}
</style>
</head>
<body>

<div class="threecol">
	<div>
		<div>
			Lorem<br />ipsum<br />dolor<br />sit<br />amet<br />consectetur<br />adipiscing<br />elit<br />Donec<br />at<br />felis<br />nibh<br />Cras<br />nulla<br />risus<br />iaculis<br />eu<br />tristique<br />et<br />lacinia<br />nec<br />neque<br />Suspendisse<br />volutpat<br />nibh<br />mauris<br />at<br />ultrices<br />justo<br />Morbi<br />sed<br />dui<br />mauris<br />sed<br />porttitor<br />diam<br />Sed<br />semper<br />mi<br />eros<br />Praesent<br />eget<br />felis<br />hendrerit<br />turpis<br />posuere<br />porttitor<br />nec<br />nec<br />lacus
		</div>
	</div>
	<div>
		<div>
			Lorem<br />ipsum<br />dolor<br />sit<br />amet<br />consectetur<br />adipiscing<br />elit<br />Donec<br />at<br />felis<br />nibh<br />Cras<br />nulla<br />risus<br />iaculis<br />eu<br />tristique<br />et<br />lacinia<br />nec<br />neque<br />Suspendisse<br />volutpat<br />nibh<br />mauris
		</div>
	</div>
	<div>
		<div>
			Lorem ipsum dolor sit amet, consectetur adipiscing elit.
		</div>
	</div>
</div><div></div><div></div><div></div><!--these empty divs add a bottom border to each column-->

</body>
</html>

Yes that is one way of getting the equal height columns but the downside is that you cannot use in-page links (fragment identifiers) when using that (one true layout negative margin) method).

It’s a shame really because its a an easy solution but as far as I’m concerned the in-page links issue is a show stopper as it effectively renders the page useless once scrolled to the destination.

If you are going to add extra divs for the borders then you may as well do the whole thing with my absolute overlay method which will work back to ie5.:slight_smile:

Example1
Example2

That is a pretty major flaw in the one-true-layout method, but maybe there’s a workaround…

Here’s a slightly more refined, IE7-compatible example of it, and this one features an in-page link that doesn’t mess up the page!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Equal Height Columns</title>
<style type="text/css">
	html, body {
		height: 100%;
		margin: 0;
	}

	.onetruelayout {
		width: 100%;
		min-height: 97%;
		padding-top: 1%;
		overflow: hidden;
	}

	.col {
		float: left;
		width: 30%;
		padding-bottom: 99999px;
		margin-bottom: -99999px;
		margin-left: 2.5%;
		background-color: lightblue;
		border: 1px solid black;
	}

	.innercol {
		padding: 4px 10px 4px 10px;
	}

	.bottomborder {
		float: left;
		width: 30%;
		margin-left: 2.5%;
		border: solid black;
		border-width: 0 1px 1px 1px;
	}

	.bottommargin {
		height: 1.5%;
	}

	.target {
		position: absolute;
	}
</style>
</head>
<body>

<div class="onetruelayout">
	<div class="col">
		<div class="innercol">
			<a href="#endofcol">GO TO END OF COLUMN</a><br />Lorem<br />ipsum<br />dolor<br />sit<br />amet<br />consectetur<br />adipiscing<br />elit<br />Donec<br />at<br />felis<br />nibh<br />Cras<br />nulla<br />risus<br />iaculis<br />eu<br />tristique<br />et<br />lacinia<br />nec<br />neque<br />Suspendisse<br />volutpat<br />nibh<br />mauris<br />at<br />ultrices<br />justo<br />Morbi<br />sed<br />dui<br />mauris<br />sed<br />porttitor<br />diam<br />Sed<br />semper<br />mi<br />eros<br />Praesent<br />eget<br />felis<br />hendrerit<br />turpis<br />posuere<br />porttitor<br />nec<br />nec<br />lacus<br />
END<span id="endofcol" class="target"></span>
		</div>
	</div>
	<div class="col">
		<div class="innercol">
			Lorem<br />ipsum<br />dolor<br />sit<br />amet<br />consectetur<br />adipiscing<br />elit<br />Donec<br />at<br />felis<br />nibh<br />Cras<br />nulla<br />risus<br />iaculis<br />eu<br />tristique<br />et<br />lacinia<br />nec<br />neque<br />Suspendisse<br />volutpat<br />nibh<br />mauris
		</div>
	</div>
	<div class="col">
		<div class="innercol">
			Lorem ipsum dolor sit amet, consectetur adipiscing elit.
		</div>
	</div>
</div>

<div class="bottomborder"></div>
<div class="bottomborder"></div>
<div class="bottomborder"></div>

<div class="bottommargin"></div>

</body>
</html>

The link actually targets an absolutely-positioned span that is next to the intended target. Works fine in IE and FF, but Chrome still crops the page for some reason. I don’t seem to have the css skillz to solve that problem, but maybe someone else does? Then again, maybe it’s time to discard the O.T.L. altogether, since there are apparently better options available!

Paul, is there any reason your techniques wouldn’t work with fluid widths, if IE6-compatibility isn’t required?

Yes I have seen similar to that absolute method before and it does seem to work for most browsers but the downside is that you can’t set your column to position:relative or you jump back to the original problem. It could still be useful in controlled situations though.

However I think that for a method to work efficiently it shouldn’t be upset or restricted by something that may be necessary to add to the layout at a later date.

The OTL is still useful for small equal height blocks that won’t have in-page links but for major columns then I don’t think its worth the risk.

Paul, is there any reason your techniques wouldn’t work with fluid widths, if IE6-compatibility isn’t required?

You can do fluid widths as well but you just have to work things out carefully. This is an old demo.

Or you could use display:table for IE8+ and the absolute overlay for ie6 and 7 as shown here.

Or if you don’t mind expressions we can remove the extra mark up for iE6 and 7 and have clean html.

I’m on the road at the moment, but when I get back to my desktop I’ll post up an approach I’ve been playing with… the HTML for it is no different than my current ‘normal’ approach to building a three column, one column fluid method… so the markup is just:


<div id="columnWrapper">

	<div id="contentWrapper"><div id="content">
		Content Area
	<!-- #content, #contentWrapper --></div></div>
	
	<div id="firstSidebar">
		First Sidebar
	<!-- #firstSidebar --></div>
	
	<div id="secondSidebar">
		Second Sidebar
	<!-- #secondSideBar --></div>
	
<!-- #columnWrapper --></div>

It is similar to the last example Paul posted… though it doesn’t rely on any of that IE conditional comment bloat… and works all the way back to IE 5.5 (if expressions are enabled)