Equal Height Blocks in Rows

Avatar of Chris Coyier
Chris Coyier on (Updated on )

There are plenty of solutions for equal height columns using jQuery (like matchHeight.js). The basic idea is to measure all of their heights and then set all their heights to that of the tallest one.

But what if there is multiple rows of blocks and you only want to increase the heights to match in the current row? This could happen from having different sized thumbnails or different amounts of text in each box.

Stephen Akins posted a neat idea on how to solve this. The idea is largely the same, test the heights of divs and set them to the tallest, but before it does that it measures the top position. From that, it is able to tell which divs belong to which row and only affect divs within that row.

Here is the whole thing. I just tweaked it a little from Stephen’s original to make it a bit more efficient.

// IIFE
(function() {

var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array();

function setConformingHeight(el, newHeight) {
// set the height to something new, but remember the original height in case things change
el.data(“originalHeight”, (el.data(“originalHeight”) == undefined) ? (el.height()) : (el.data(“originalHeight”)));
el.height(newHeight);
}

function getOriginalHeight(el) {
// if the height has changed, send the originalHeight
return (el.data(“originalHeight”) == undefined) ? (el.height()) : (el.data(“originalHeight”));
}

function columnConform() {

// find the tallest DIV in the row, and set the heights of all of the DIVs to match it.
$(‘.blocks’).each(function() {

// “caching”
var $el = $(this);

var topPosition = $el.position().top;

if (currentRowStart != topPosition) {

// we just came to a new row. Set all the heights on the completed row
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest); // set the variables for the new row rowDivs.length = 0; // empty the array currentRowStart = topPosition; currentTallest = getOriginalHeight($el); rowDivs.push($el); } else { // another div on the current row. Add it to the list and check if it's taller rowDivs.push($el); currentTallest = (currentTallest < getOriginalHeight($el)) ? (getOriginalHeight($el)) : (currentTallest); } }); // do the last row for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) { setConformingHeight(rowDivs[currentDiv], currentTallest); } } // If the content might change... probably debounce this and run it. // $(window).resize(function() { // columnConform(); // }); // DOM Ready // You might also want to wait until window.onload if images are the things that are unequalizing the blocks $(function() { columnConform(); }); })(); $('.blocks') would be changed to use whatever CSS selector you need to equalize. Or have the function accept a selector as a param or something.

What About Fluid Width?

One of the main points of not using a table for this is that floated divs can rearrange themselves based on the available horizontal space, which is nice for fluid width. We can adjust the above code to deal with that as well. Basically the first time this is run we’ll measure the height of each block and remember it with jQuery’s data() method. Then when the window is resized, run the code again but use the original size to adjust the rows, not the new size.

The demo for this is fluid width. If you want that code, just view source and snag it:

View Demo

Wish it didn’t have the jQuery dependency?