The Matching Columns Script Video Tutorial: Matching CSS div Heights

April 4th, 2006

One of the fundamental problems people have with CSS page-level layout is matching CSS div heights. Others might call this ‘matching column heights’ in web pages.  

In this article/video (see below,) we are going to solve this problem using a lesser known JavaScript method: the Matching Columns Script.

Let’s start  out by checking out a diagram that illustrates the problem:

Diagram of div heights problem.

People have come out with different solutions including the ‘Faux columns’ hack:  using a vertically tiled background image to create the illusion of a column.

The ‘Faux columns’ hack/trick works, but it does have some limitations:

  • You have to mess around with background images when creating the fake/faux columns effect – there is even more mucking about when you have liquid layouts.
  • You won’t be able to use CSS border styling (on your div’s that create the columns) because it would reveal the hack.

THE BETTER WAY TO HANDLE THIS PROBLEM: DOM SCRIPTING (JavaScript)

JavaScript (sometimes called ECMA script,) is the programming language built into all the browsers that allow geeks/nerds, to have practically total control over how things appear in a web page – it’s very powerful.

Note: DOM scripting (the term,) is a quick way to describe using JavaScript to control a web page’s structure. If this makes no sense, don’t worry about it as you need no programming knowledge to use the technique that is covered here. 

 WHY IS THE JAVASCRIPT METHOD BETTER?

You are better off with the JavaScript method (rather than the ‘Faux columns’ hack, ) because:

  1. Once it is applied, you don’t have to worry about it as it automatically adjust itself to change with your page(s).
  2. It is much easier/faster to apply than the ‘Faux columns’ hack.

 GETTING STARTED

Attached with this article you will find the files you need to apply the script:

  1. The Javascipt file.
  2. The CSS document.
  3. A sample web page that puts it altogether.

Now it’s time to watch the video to learn how to use it.

 MATCHING DIV HEIGHTS VIDEO


CONCLUSION

There is one downside to this technique:

It won’t work if people have JavaScript turned off. Fortunately, the vast majority of people out there have it on. Last time I checked my own stats, nobody had JavaScript disabled.

That said, though it looks a lot better when your columns heights match, I would not consider it mission-critical to a website. That is to say; people will still be able to use the website, so I am willing to accept that for some rare (paranoid) individuals, the columns will not match.

Source Files

 

100 Responses to “The Matching Columns Script Video Tutorial: Matching CSS div Heights”

  1. Ryan says:

    Hey,

    I have found an issue with this script. I have attempted to add an onload event to the tag. Once there is an onload event the columns fail to work. For reference, I was using the google maps API (And it requires a body onload function)..

    No clue why this occurs. Without the onload event it works perfectly. This also occurs with any onload event.. Not GMAPS related

  2. @Ryan,

    It is not clear to me: are you trying to call both function on the onload event?

    Can I see the way you are calling them?

  3. Ryan says:

    Hey there,

    Im not trying to call the javascript via body onload. I’m loading it the standard way ( )

    The problem is that when I add an ‘onload’ event to the body tag for something else, for some reason it interferes with the matching columns and then fails to work

  4. Ryan says:

    Standard way:

  5. Chris says:

    Ryan, Stefan

    I am experiencing the same problem with having an onload call in the body element.

    Reason its there is I have a form, and for usability I am using the onload call to place the cursor into the first form field.

    As soon as I remove the onload function from the body element the columns match up like butter.

    Is there a way for the matching_columns script to work in harmony with a body onload?

    thanks

  6. Someone has submitted a new version of the script – the details are in the code:

    /*
    Derived from a script by Alejandro Gervasio.
    Modified to work in FireFox by Stefan Mischook for Killersites.com

    Modified to work with multiple class groups also with elements with multiple class names
    by Jonathan del Mar (dec-14-2006)

    How it works: just apply the CSS class of ‘column’ to your pages’ main columns.

    to work with different classes
    add

    by Jonathan del Mar

    by default the script will call
    matchColumns();
    and the default class_name is ‘column’
    (see the bottom of this script)
    by Jonathan del Mar

    */
    matchColumns=function(my_class){

    var divs,contDivs,maxHeight,divHeight,d;

    // get all

    elements in the document

    divs=document.getElementsByTagName(‘div’);

    contDivs=[];

    // initialize maximum height value
    maxHeight=0;
    if (!my_class) {
    my_class = ‘column';
    }

    my_regex = new RegExp(‘(.* |^)’ + my_class + ‘( .*|$)’);

    // iterate over all

    elements in the document

    for(var i=0;i

    // make collection with

    elements with class attribute ‘container’

    //if(/\bcolumn\b/.test(divs[i].className)){
    // modified by Jonathan del Mar to match ‘column’ in multiple classes

    if(my_regex.test(divs[i].className)){
    d=divs[i];

    contDivs[contDivs.length]=d;

    // determine height for

    element

    if(d.offsetHeight){

    divHeight=d.offsetHeight;

    }

    else if(d.style.pixelHeight){

    divHeight=d.style.pixelHeight;

    }

    // calculate maximum height

    maxHeight=Math.max(maxHeight,divHeight);

    }

    }

    // assign maximum height value to all of container

    elements
    for(var i=0;i contDivs[i].style.height=maxHeight + "px";
    }

    }

    // Runs the script when page loads

    window.onload=function(){

    if(document.getElementsByTagName){

    matchColumns();
    if (columns) {
    for(var i=0;i
    matchColumns(columns[i]);
    }
    }
    }

    }

  7. Frances says:

    I used your tutorial and I am very impressed by the video as well as the end result; much better solution to others I have come across while searching for a solution to this problem.

    I have one issue however … although my left hand div now has extended in length, there is a 1 pixel gap between it and the footer image. Any suggestions on why this may be?

    Thanks for your help

  8. Rik says:

    Great stuff! I put it in the new wordpress theme I’m building, and theres a slight problem: now it makes the colums way too high, resulting in lots of empty space between posts.

    how can I fix this? The CSS for the two columns is this:

    #flare {
    float:left;
    width:142px;
    text-align:left;
    font-size:11px;
    color:#FFFFFF;
    font-family:helvetica;
    color:#FFFFFF;
    padding: 10px 4px 0px 10px;
    line-height:130%;
    background: #2D2D2D;
    }

    #post {
    width:530px;
    text-align:left;
    margin-left:156px;
    font-family: helvetica;
    font-size: 10pt;
    line-height: 130%;
    padding: 6px;
    font-family:helvetica;
    color:#000000;
    }

  9. @Frances,

    I would have to see your layout, but keep in mind that the script simply compare the two or more

    ‘s that you give and and matches their heights … nothing more.

    So I would guess that the script is just revealing some other aspect of your layout that was not apparent before you applied it.

    I’m glad you liked it.

    Stefan

  10. Rik says:

    I’ve put a screenshot of what happens at http://www.trythisonforsize.net/downloads/screenshot.png

    Hope you can help me out…

  11. Rik says:

    I think i know what happens: it makes every post the size of the longest one; this is probably not going to work for a blog right?

  12. @Rik,

    This has to do with the CSS code and the structure of the blog template and not whether or not it is a blog.

    You would have to dig into the template code to work it out.

    BTW: did you design the templates?

  13. Chris says:

    Hi Stefan,

    thanks a lot for your script, it really saved me a lot of time.
    Unfortunately I discovered a small problem when i was working on a layout with 3 divs where two of them have a 1px border.

    The div without border is missing 2px…as far as I can see the borders are drawn as outlines!

    I tried to solve this problem with additional CSS styles but I couldnt find any proper solution.

    Is there any way to expand your script with an additional class e.g.:
    .column_no_border = maxHeight +2px or .column_border = maxHeight -2px ?
    Maybe you could put me in the right direction (because i dont have any JS skills ;)

    Thanks in advance
    Chris

  14. Hi,

    I haven’t looked at the script in a while. But I suspect that what you want is possible.

    Sorry I haven’t the time to look into now, but maybe later.

    Stefan

  15. Ahmad says:

    Goos script, thnx 4 sharing it. I’ve noticed when implementing it that it is very slow 2 apply onload. I’ll have 2 hover over some javascripted links in order 2 get it going! Do u have any idea y would that happen?

  16. I haven’t noticed much of a speed issue myself … but I haven’t tested every possible layout.

    That said, I would suggest creating a basic 2-3 column page and test the script as your gradually add complexity to your page layout.

    .. Hopefully this process will help you identify what is slowing things down.

    Stefan

  17. […] I decided to create another blog post to make it easier to find the updated version of the important matching columns script – it was buried in the originals article’s comments. […]

  18. Rob says:

    like the script… but it doesn’t work with multi-column liquid layouts as far as i can tell…
    seems to only work on reload for me. is there any way of adding an on_resize hook?

  19. @Rob,

    I haven’t tested all possible layouts … that said, it should work whether it be liquid or not … the logic of the programming is related to the heights of the targeted

    ‘s.

    I would take a closer a closer look at how you apply it.

    PS: we may wan’t to check out webshapes.org for a growing collection of open source templates.

    Stef

  20. Dylan says:

    Hi Stefan.

    Great script, except…..

    I have used it on a 3 column layout but have found when the centre “content” column has dynamic content (ie generated by php) the column height stops at the height of the tallest other column (in this case the menu). When I populate the centre colum with regular html it works fine.

    Could you offer any advice please :)

    Regards.

  21. @Dylan,

    My guess is that it is a timing issue where the script is being fired before the content has been filled in completely.

    .. This is a hard one to explain (and might not make any sense,) but what it comes down to (in theory) is that the script needs to be delayed a second or two before firing

    … perhaps create a function that calls setTimeout() that calls the columns script.

    ?

    Another option is to change the order that which the columns appear in the page’s code – make sure the dynamic column comes in first.

    Hope that helps,

    Stefan

  22. steve says:

    Stefan,

    The script worked fine in IE 7 and Firefox, but I had a javascript problem with IE 6 (same problem, tested on 2 browsers). The problem was that the div Height was returning NaN. This could be because of my goofed up styles, but I was able to fix it by adding the following:

    if (isNaN(maxHeight)) {
    // GRRRR IE 6 behaving badly
    if (pageName==’somepage’) {
    maxHeight=3730;
    }else if (pageName==’anotherpage’) {
    maxHeight=825;
    }else {
    maxHeight=0;
    alert (‘missed one: ‘ + pageName);
    }
    }

    The pageName is sent in using the form’s onload event like this:

    where doLoad calls the matchColumns(pageName):

    function doLoad(ButtonName) {
    setButtonBackground(ButtonName) ;
    if(document.getElementsByTagName){
    matchColumns(ButtonName);
    }
    }

    To get it to work, I redefined matchColumns like this:
    matchColumns=function(pageName){
    ….

    }

    Kludged, but working.
    Thanks for the post, by the way.
    Cheers,
    Steve

  23. @Steve,

    Thanks for sharing your modification with us.

    Stefan

  24. Michel says:

    Thanks for this script, it’s great!

    After reading the complete comments, I couldn’t find the source of the updated script to manage multiple calling for different set of heights (either the code was badly rendered in the replies of the link Stefan provided is empty, and I needed to call it 4 times) so I made some small updates and thought I’d share it with everyone.

    From the original script (available to download), I replaced 2 lines :

    replaced the function first line
    matchColumns=function(){
    by
    function matchColumns(classname){

    and the IF
    if(/\bcolumn\b/.test(divs[i].className)){
    by
    if(new RegExp(“\\b” + classname + “\\b”).test(divs[i].className)){

    So now I can call the same function and passing the class name in parameter like this :

    matchColumns(‘column’); // class=column
    matchColumns(‘maincolumn’); // class=maincolumn

    Enjoy :-)
    Michel

  25. Brandon says:

    I have applied this script to one test page, but it doesn’t seem to work. Any idea why? The test page is http://www.presentationsdirect.com/Laminators/GBC-Laminators_test.asp.

    If it was working correctly, the divLeftColumn is supposed to extend down to the length of the divContent and divLeftColumn would have a gray background.

  26. Bob Hope says:

    Michel (or anyone),

    I dont understand how to call the javascript function from within html.

    I have 2 different situations on one page where Id like to use this script but only one will work. I tried creating two different js files )renamed and called to each, but only one will work. Please help! Thanks so much

  27. Tom says:

    Dear Stefan,

    Many thanks for this script. It works perfectly for me. However I have a question. Currently the function matchColumn is triggered by windows.onload. Is there a possibility that I also can trigger the matchColumn function when a browser window is resized.

    I’ve tried:

    windows.onresize=function() {

    if {

    if(document.getElementsByTagName){

    matchColumns();

    }

    }

    However that doesn’t seem to work. Any idea how I could fix this? Many thanks for your response!

    Regards,

    Tom

  28. Debbie says:

    This script works well, but when I try to add a slideshow script to my page, the matching columns script stops working. The slideshow is triggered with onload in the body tag. Any idea why this is happening?

    Thanks,
    Debbie

  29. Chad Williams says:

    Hey Stepan,

    I have used your script multiple times without any problem. For some reason I can’t seem to figure this one out. Currently designing a 2 col layout, header, content, nav, footer. content and nav positioned relative with the class=”column” assigned to each div. the script to call the js is in my code. the js is on the server ect. any feedback would be greatly appreciated.

  30. Chad Williams says:

    Just in case anyone wants to know i figured out my problem. as a looked into how the matching_columns.js worked i noticed on line 67 if has a onload function. that got me curious b/c I was using this piece of code to do the swap image restore function. i removed this and just had my tage and my columns matched perfectly.

  31. veronica says:

    i just wanted to drop you a line and say thank you so much for publishing this script. it worked perfectly with the site i’m working on, what a relief! thanks so much. :)

  32. Veronica,

    Glad to hear you found it useful.

    When I ran into the columns problem, I knew that I had to get a fix out there for everyone.

    Stefan

  33. Jim Rudnick says:

    I’m having MUCH troubles trying to get the cols to match. I believe that I’ve got the proper files/code inserted as is needed, but the dang left hand side gold coloured will NOT stretch enough to match the main content .

    PLUS, I also used the same class on the overall so that the footer will always drop down to the bottom of the overall content and that 1px black border will always be outside all content….

    What am I doing wrong?

    Test page is at — http://www.kkt-testserver.com/Lions/index.html

    Can NOT get this straight!!!! Dang it!

    Jim

  34. Jenga says:

    Have a fairly hacked up site-but I was able to get it to work on FF and IE7, ie6 not so much the left drops down about 200px lower than it should and doesn’t fill. What am I doing wrong?

  35. @Jenga,

    It is very hard to help without code samples … That said, please post your question to the forum so other people can get involced:

    http://www.killersites.com/forum/

    Stefan

  36. Stefan says:

    Hello everyone. It’s a great script. I have a question. I try like Michel say “multiple calling for different set of heights” with the updates

    “replaced the function first line
    matchColumns=function(){
    by
    function matchColumns(classname){

    and the IF
    if(/\bcolumn\b/.test(divs[i].className)){
    by
    if(new RegExp(”\\b” + classname + “\\b”).test(divs[i].className)){

    So now I can call the same function and passing the class name in parameter like this :

    matchColumns(’column’); // class=column
    matchColumns(’maincolumn’); // class=maincolumn

    But it doesn’t work. I’m sorry, I’m pretty new in this, so I apologize if my question sounds stupid. Here is a little example that I’ve try to do.

    http://smile.sellinet.net/col/tmp_NEW.html

    If anyone can help, I would be grateful. Excuse me, for my bad English.

  37. Marc McDonald says:

    Thanks for the hack – it saved my butt on a project for work! Good vid too.

  38. Brian Hadaway says:

    Excellent tutorial! Worked perfectly for me. Thanks!

  39. Jaco says:

    I don’t see how this works Stefan. If you would give the navigation background a different color in your example, maybe some of us newbies could see the columns being matched up. However, both have no background (white default).

    I used your files and only changed the following:

    1) changed the color of the navigation column (in the style sheet) to color: #CC0000. (so I could possibly see the difference).

    2) Decreased the quantity of text in DIV “CenterDoc” to only 2 paragraphs of data.

    I have posted the results for viewing. The navigation column continues down to infinity, where the CenterDoc column terminates a little after mid page going down. Am I missing something here? Shouldn’t the left navigation menu (in red) cutoff at the same point where the text in the CenterDoc column ends?

    Please any advice appreciated.

  40. Jaco says:

    Stefan,

    I stand corrected. It seems to be working in IE, but in FF the left navigation column (red) just continues down to infinity. So, perhaps FF is not picking up the Java Script?

    Any ideas?

    Thanks

  41. stefan says:

    unfortunately, I have no ideas for now :(

  42. moisea says:

    i don’t know what i am doing wrong but it’s somehow not working under IE6.checked and rechecked my codes still nothing.i am using a w3c css template.
    any idea on how to fix it? thank you.

  43. Brian says:

    Absolutely the best! Thanks. This made my life sooooo simple. I am moving from all html to mostly CSS and you saved me gobbs of work!

  44. Michelle says:

    Hi, I am trying to incorporate your script into WordPress, as the faux columns technique simply won’t work with my template. I have copied the script src line into my header.php template, and have applied class=”column” to the div ids, but it does not seem to work.

    (Currently I am only testing in Mac/Firefox 2.0, but will test other browsers/platforms once I get this aspect of the site sorted out).

    Any suggestions on what I might be doing wrong?

  45. Hi Michelle,

    It is hard to diagnose without seeing all the code. But let me think …
    Be sure that you are loading the .js file properly … check your paths.

    Stefan

  46. Michelle says:

    Hi Stefan,

    Here is the header.php code. I tried renaming the script path to the full url, but that didn’t seem to help.

    <meta http-equiv=”Content-Type” content=”; charset=” />
    <meta name=”generator” content=”WordPress ” />

    <link rel=”stylesheet” href=”” type=”text/css” media=”screen” />
    <link rel=”alternate” type=”application/rss+xml” title=”RSS 2.0″ href=”” />
    <link rel=”alternate” type=”text/xml” title=”RSS .92″ href=”” />
    <link rel=”alternate” type=”application/atom+xml” title=”Atom 0.3″ href=”” />
    <link rel=”pingback” href=”” />

     

    <a href=”/” title=” “>

  47. Michelle says:

    Sorry, that didn’t seem to work.

    /*

    <meta http-equiv=”Content-Type” content=”; charset=” />
    <meta name=”generator” content=”WordPress ” />

    <link rel=”stylesheet” href=”” type=”text/css” media=”screen” />
    <link rel=”alternate” type=”application/rss+xml” title=”RSS 2.0″ href=”” />
    <link rel=”alternate” type=”text/xml” title=”RSS .92″ href=”” />
    <link rel=”alternate” type=”application/atom+xml” title=”Atom 0.3″ href=”” />
    <link rel=”pingback” href=”” />

     

    <a href=”/” title=” “>

    */

  48. Michelle says:

    Apologies again. I obviously don’t know how to copy&paste code so it shows correctly in the post.

  49. Chiel "Tengu" Huijskes says:

    Stefan, I am so happy I can cry. Yes, perhaps I should get out more ;) I have made a very complicated template system for a CMS called Mambo and the last thing I needed to do was this. I didn’t think I’d ever manage. It is great! Everlasting gratitude from Tengu!

  50. John Webster says:

    How can I add !important to the height? I tried change “px” to “px !important” but that did not work. Any help?

Created By Stefan Mischook  |  Site Map  |  Top of page  go to top of page