Sunday, July 6, 2008

Equal Height Columns with MooTools

There are a number of Javascript solutions around for creating equal height columns in a design. They all work in pretty much the same way - you generally specify the required columns in the height function, and run it after the DOM is available.

On the Radio NZ site I recently ported our old column function to use the Mootools library.

Here is the old function:
/* SetTall by Paul@YellowPencil.com and Scott@YellowPencil.com */

function setTall() {
if (document.getElementById) {
var divs = Array();
var list = new Array('cont-pri','cont-sec','hleft','hright','features','snw');
count = 0;
for (var i = 0; i < list.length; i++) {
if ( (temp = document.getElementById(list[i]) ) ){
divs[count] = temp;
count++;
}
}

var mH = 0;
for (var i = 0; i < divs.length; i++) {
if (divs[i].offsetHeight > mH) mH = divs[i].offsetHeight;
}
for (var i = 0; i < divs.length; i++) {
divs[i].style.height = mH + 'px';
if (divs[i].offsetHeight > mH) {
divs[i].style.height = (mH - (divs[i].offsetHeight - mH)) + 'px';
}
}
}
}
The first part of the function places the ids we want in an array, then checks to see if these are valid and storing them in another array of they are. This check is required as the hleft and hright divs are only found on the home page.

The second loop finds the tallest div, and the last loop changes the height of each div to that value (taking into account any CSS padding).

The Mootools version is much simpler:
function equalHeights() {
var height = 0;

divs = $$('#cont-pri','#cont-sec','#hleft','#hright','#features','#snw');

divs.each( function(e){
if (e.offsetHeight > height){
height = e.offsetHeight;
}
});

divs.each( function(e){
e.setStyle( 'height', height + 'px' );
if (e.offsetHeight > height) {
e.setStyle( 'height', (height - (e.offsetHeight - height)) + 'px' );
}
});
}
The first call to $$ returns only valid divs, eliminating the need to check. The each iterator is then used twice - the first time to get the maximum height, and the second to set all the divs to that height.

7 comments:

Nigel Ramsay said...

Using the Prototype library, arrays implement the Enumerable interface. And this provides a max function that allows something like this:


var height = divs.max(function(div){
  return div.offsetHeight;
});


There may be something similar in MooTools, so take a look.

Another issue to be aware of is that the $ operator is a lot faster than the $$ operator. The $$ operate has to parse the entire document tree. More details on the Prototype version here.

Matthew James Taylor said...

I find it's better to forget JavaScript and simply use equal height columns with pure CSS. Then you can be sure it will always work in all browsers.

Richard Hulse said...

Interesting approach...

In our case we have different numbers of columns on some pages, and an extra one if the page is wide enough.

We had a very short time to deploy the design and I ran out of time to solve some of the finer layout problems with CSS.

I pressume you approach would mean I'd have to vary the number of outside containers dynamically somewhow?

As an aside, we are just converting all the code to be jQuery based.

Webagentur said...

Thank you ... this has me very helped.

Lorenzosjb said...

I have noticed that if one of the columns load a external file (using the load function), then the columns are improperly ajusted. This happens also with JQuery. It is a design flaw?

Richard Hulse said...

If you load content dynamically, you have to call the equalheights function after the load (put it in the onsuccess callback) and this will recalculate the heights.

lsjb said...

Dear Richard: Thanks, your input helped me to get the thing done! Regards, Lorenzo