CSS Only Equal Height Columns

Creating fluid and responsive equal height columns without any JS or CSS hacks

Website designers often want to create columns that are equal but still dynamic in height. i.e. the height of all the columns should be dictated by the largest one. This is not that straight forward though using only HTML and CSS and there are many different ways to do it. Some are more convenient than others, some use JavaScript for the sake of having a simpler mark-up.

I recently had a go on it myself, using a method that I haven't seen on any of the popular (albeit already old) tutorials: using "background divs" behind the actual content divs.

css-tricks.com has a comprehensive list of methods for Fluid Width Equal Height Columns. Many of these methods use simple backgrounds or column oversizing in conjunction with overflow:hidden in order to get the visual effect of having columns that are all equal in height. However, if you want to have more complex backgrounds or borders on your columns, these methods aren't suitable. We need to assign those CSS properties to block elements that are properly aligned with our content.

Thus comes the idea of simply positioning additional block elements in the background of our actual columns. These can be independently aligned and positioned according to the layout of our columns and can be individually styled.

Let's have a look at the mark-up first:

<div id="container">

	<div class="backgrounds">
		<div class="column"></div>
		<div class="column"></div>
		<div class="column"></div>
	</div>

	<div class="column">...</div>
	<div class="column">...</div>
	<div class="column">...</div>
	
	<div style="clear:both;"></div>

</div>


We have a .column class representing our simple fluid column layout. Of course we could also use a grid framework here. Before our actual content columns, we have a duplicated column layout inside a .backgrounds div. The columns inside will have the same size and margin as our regular content columns, but its parent will be positioned absolutely behind those.

The .backgrounds section does not have to be put in front of the regular content columns inside the DOM, but this way the content columns will be rendered on top of the background columns, without having to define a z-index.

Lastly we have a clearing div, so that our #container has the correct height according to the content columns.

Now on to some basic CSS:

/* use border-box box-sizing */
div { 
	box-sizing:border-box; 
	-moz-box-sizing:border-box;
}

/* column container */
#container { 
	margin:0 -2.1666%; 
	position:relative; 
}

/* column layout */
.column { 
	position:relative; 
	float:left; 
	width:29%; 
	margin:0 2.1666%;  
	padding:1.2em; 
}


First we use box-sizing:border-box so that we can assign borders and paddings more easily to our fluid width content and background columns. Our #container gets a negative margin to counteract the relative margin of our fluid column layout. It also needs position:relative because we want to absolutely position our .backgrounds element within the constraints of the #container. The column layout is pretty standard. But we additionally assign a relative position to our content columns, so that they will be rendered on top of the background columns.

Now the background columns can be positioned and sized as following:

/* background container */
.backgrounds { 
	position:absolute;
	width:100%;
	height:100%;
}

/* background columns */
.backgrounds .column {
	height:100%;
}


The .backgrounds container gets an absolute position, with 100% width and height. The .column elements within already have the correct width and margin from the column layout, they simply need an additional height of 100%.

We can now freely add some visual styles to those background columns, like background colors, gradients, different borders and border-radii. Example result:

Left Column

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.

Middle Column

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

Right Column

Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.


A standalone version can also be viewed here. This also includes a media query for a responsive layout. The columns will break down linearly at a viewport width of 768px. At this breakpoint, the regular content columns get the visual styling of their respective background columns and the background columns will be hidden. And here is a jsfiddle.

This solution should work in all modern browsers, including IE8. It allows you to freely style your fluid (and responsive) equal height columns. The downside is, that you have to add additional mark-up (that mimicks your content column layout) to your template and also manually handle the styles within your media queries.

 

I don't know why the other solutions are so popular in all the other tutorials. May be because it requires the duplication of your column layout just for the equal height background columns. But even so, I think it's far easier and more straight forward than anything else.

 

Note: when using Grid Frameworks, you may need to put the .backgrounds div after your regular content columns within the DOM, depending on the framework. In that case you'll also need to assign a left:0 and top:0 position to the .backgrounds div, as well correct z-indices for the background and content columns respectively (example on jsfiddle with Twitter Bootstrap).

Last update: 5. Feb 2014

Go back

Add a comment

Comment by Daniel Daly |

I'm new to media queries and responsive web design. What exactly would be the css for the media query you have in the example? I'd like my columns to stack as well.

Comment by Fritz Michael Gschwantner |

You can view the media query in the source of this example: http://www.spikx.net/files/blog/equal-height-columns/v2.html

Short version:

/* responsive */
@media only screen and (max-width:768px) {

    body { margin:1.6em; }
    #container { margin:0; }
    .column {
        float:none;
        width:100%;
        margin:0 0 1em 0;
        
        border-radius:10px;
        background: #7db9e8; /* Old browsers */
    }
    .backgrounds { display:none; }
}

Short description:

  • Remove negative margin of #container
  • remove float property of .columns and expand to 100% width (or auto)
  • add background property to .columns instead of the columns within .backgrounds
  • hide .backgrounds

Hope that helps :)

Comment by Paul |

Simple, pure CSS solution that works like a charm. I also don't know why its not more popular, but glad I found it. Thanks!

Comment by Marcos |

Its fantastic, but what can I do if i want 4 or 5 columns with the same efect?

Thanks

Reply by Fritz Michael Gschwantner

Here is an example using the twitter-bootstrap grid: http://jsfiddle.net/QBLrC/

Just change the column layout accordingly.