Equal Height Columns with jQuery

Creating equal-height columns with CSS is sometimes a bear. But who needs the hassle of faux columns, “clear” divs and the rest? With this bit of jQuery, you can easily equalize the heights of any group of elements.

This technique was born of frustration. I ran into two layout problems while working on the redesign of CSS Newbie one afternoon, and both were directly related to the varying heights of elements.

The first problem was in the footer. If you look closely, you’ll see that there is a nice subtle two-tone border in between each of the columns in the footer.


That style wasn’t as easy to create as it might look. At first, I was going to make the border part of the background image, and just edit my content to suit. But that’s very un-web of me: the beauty of the web is we’re not constrained by sizes nearly as much as print designers.

So instead, I decided to make the borders the old-fashioned way, as legitimate CSS borders. Of course, to get it exactly the way I wanted I had to resort to a bit of a hack, matching light borders on the right side of one column with a dark border on the left side of the following column. The hack works beautifully… as long as all three of my columns are of equal height. Otherwise, the borders don’t match:

The second problem I ran into was in the “recent articles” section of the homepage. I wanted to feature four articles, but I didn’t want them to take up a ton of space. To accomplish that, I made the article blocks half as wide as my space and floated them into two columns with two rows.

And as long as I’m lucky and all my excerpts are the same length, that works fine. But the instant something is a line or two longer or shorter, one of the more annoying flaws with floats rears its ugly head. If I have a long excerpt in spot 1, followed by a short excerpt in spot 2, the excerpt in spot 3 won’t float all the way to the left: it’ll get caught on the edge of the first excerpt instead.

So again, I have a height-related problem. “If only there was an easy way to equalize heights without resorting to a table,” I thought thusly.

And so I set out to find an easy way. And after a bit of fiddling with jQuery, I was able to find a workable solution. Here’s the function I ended up with:

function equalHeight(group) {
	tallest = 0;
	group.each(function() {
		thisHeight = $(this).height();
		if(thisHeight > tallest) {
			tallest = thisHeight;
		}
	});
	group.height(tallest);
}

You can see it in action here. What this function is doing is:

  1. Sets a variable, “tallest,” to zero.
  2. Loops through each of the items in the group we’ve defined.
  3. If the current item is taller then the previous “tallest” item, it becomes the new tallest item.
  4. Once we’ve looked at all the items, they all get their height reset to be the same as the tallest of the group.

So in order to equalize the heights of both my footer columns and my recent articles, all I needed to do was something like this:

$(document).ready(function() {
	equalHeight($(".recent-article"));
	equalHeight($(".footer-col"));
});

Which just waits until all my elements are done loading (so that the heights can be computed accurately), then sets both the heights.

That’s all there is to it! This function is good for fixing wily floats without clears, creating nice equal-height column designs without needing faux columns, and probably half a dozen things I haven’t thought of yet. I’m sure you’ll be able to find a use for the script someday… after all, I managed to find two uses in a single afternoon!

31 Comments

  1. Bram Van der Sype said:

    That’s a very handy thing you’ve got there. A while back (when I just started CSS) I believed in the “all things css, no javascript whatsoever” ideology. I soon found out creating equal height columns with pure CSS was a bitch.

    I found a piece of javascript that worked brilliantly, but it was quite long. Now, with some jQuery love, it’s easy to do.

    Thanks!

  2. On December 08, 2008
    10:16AM

    Joe McCann said:

    Nice, but what happens when JS is turned off?

  3. On December 08, 2008
    10:25AM

    Steph Adamo said:

    I’m pretty excited to use this, but i’ve never used jquery before so i’m admittedly pretty ignorant about how it works. Won’t i need the jquery.js file in order to implement it?

  4. On December 08, 2008
    10:45AM

    Rob Glazebrook said:

    @Bram: Thanks! I’m hoping it will be helpful to people.

    @Joe: Without JS, your columns/boxes/whatever will look exactly as they would have looked before you found this lovely script. :) The idea is, get your columns close with CSS, and then perfect them with JS. However, I’d really think that the vast majority of people would be running JavaScript these days. Too many websites use it to ignore on purpose…

    @Steph Yeah, you’d need the jquery.js file as well as this script. Basically, you run jQuery first:

    <script src=”jquery.js”></script>

    Then below that, you’d put this function inside its own <script> tag.

  5. Ben Reimers said:

    Very handy! I’ve just been getting into jQuery and have been following handy little hints like this closely. It’s a pity something like this isn’t simply a part of CSS, but that’s the Internet. Thanks for sharing.

  6. jaredmellentine said:

    I had just written a jQuery function for this last week. I run the function on all the children of a parent container (passed through the jQuery object). Other than that, we wrote our functions about the same. But here’s mine anyway:

    (function(jQuery) {
    jQuery.fn.equalHeights = function() {
    var maxheight = 0;
    jQuery(this).children().each(function(){
    maxheight = (jQuery(this).height() > maxheight) ? jQuery(this).height() : maxheight;
    });
    jQuery(this).children().css(’height’, maxheight);
    }
    })(jQuery);

    You could extend it a bit more to give a minimum height, too:

    (function(jQuery) {
    jQuery.fn.equalHeights = function(minheight) {
    var maxheight = minheight || 0;
    jQuery(this).children().each(function(){
    maxheight = (jQuery(this).height() > maxheight) ? jQuery(this).height() : maxheight;
    });
    jQuery(this).children().css(’height’, maxheight);
    }
    })(jQuery);

  7. jaredmellentine said:

    I forgot to mention how you would call the function:

    jQuery(’#mycontainer’).equalHeights();

    Or with a minimum height of 300px:
    jQuery(’#mycontainer’).equalHeights(300);

  8. On December 10, 2008
    11:26AM

    Chris Raymond said:

    In your example, if you resize text only, the columns do not stay equal in height (well, the backgrounds do, but the text overflows under the boxes)

  9. Rob Glazebrook said:

    @jaredmellentine: D’oh! You beat me to it. I was planning on releasing a plugin based on this script yet this week! Actually, I may still… our functions are technically a little different. However, you’ve given me some good ideas for how I can extend the function I’ve written. Thanks!

  10. Grant Palin said:

    This is very timely, as I am working on a new theme and was needing some equal-height columns. So simple, yet so useful.

    @Chris Raymond: I have noticed this too. But if you refresh the browser window, the columns will be redrawn to contain the text. In Firefox anyway…The same applies for sizing text smaller, the columns will not automatically shrink.

  11. On December 11, 2008
    12:45AM

    jaredmellentine said:

    @Chris and Grant: I guess it’s about time someone write a jQuery event handler for text zoom.

    http://design.mellentine.com/2008/12/11/javascript-the-start-of-a-jquery-zoom-event-handler/

  12. Phil said:

    Could this be used on grouped columns, so each box is only adjusted to others in the same ‘row’?

    I toyed around with a loop function but being a jQuery novice, couldn’t quite get my head around it!

  13. jaredmellentine said:

    I finished the jQuery zoom plugin, which may help the issue brought up by Chris. You can check it out here: http://www.dzone.com/links/zoom_event_handling_with_jquery_plugin_demo.html

    @Rob: The more I think about this, maybe using the min-height CSS property instead of height would help this issue as well. It wouldn’t keep the columns the same height if you zoomed in, but it should (in browsers that support min-height) extend the container so that the text doesn’t flow out of it.

  14. On December 13, 2008
    12:05PM

    Rob Glazebrook said:

    @Jared: Thanks for the plugin! I’ll be trying it out. Although I’m not sure I agree with using min-height as a workaround. I understand that would fix the overflow property. But as soon as I switch to using min-height, I have an equalHeights plugin that no longer guarantees equal height elements. That seems counterintuitive to me.

  15. jaredmellentine said:

    @Rob: I’ve just never been a fan of overflow: auto, except for specific cases. It’s a designer preference to have extra scrollbars or to have containers that don’t line up. I prefer fewer scrollbars because it means that my content is visible without an extra scroll, and I just think it’s a better user experience. Neither solution is ideal. I guess the best way to handle this would be to have some sort of zoom event handler. =)

    Most importantly, this issue (zooming that breaks layout) is an infrequent issue. Not only that, but it would be resolved the next time the page loads. It may just be a moot point.

  16. On December 17, 2008
    11:38PM

    Richard said:

    Your example shows that it works very nicely in FireFox (3.x Mac).

    Not so much in Safari (Mac). Not sure why, but I do notice that it fits in the default font size, but as I increase font size the text runs down through the bottom of columns [and: width of entire containing area does NOT expand - which it does in FireFox (both horiz & vert)].

    Also, I’m wondering if your approach works with various settings for WIDTH of div: since FF wants to expand it as type size grows & Safari does not. Might be worth testing re: what varieties of style respond well (fixed-width; fluid; flexible; %, etc)

    It’s a challenging problem: hats off to you for introducing a new approach!

  17. Sedat Kumcu said:

    Thanhs thanx thanx maan. Useful and very easy method and understandable article. ;)

  18. Sarah said:

    I’m using your script with mixed success. On some pages I have it running on two columns and it seems to work fine. However, I am also trying to run it on a page with four columns (using a separate class name) and it seems that about 3 out of every 5 random refreshes it will calculate the height incorrectly, resulting in the four columns overlapping whatever is underneath. Any suggestions? Is there any way to tell the script to wait until the document is ready, then wait an additional couple of milliseconds?

  19. On March 19, 2009
    11:53AM

    Kevin Rapley said:

    This is a lovely script and will work really nicely with a layout based on widths in em sizes that has to be seriously hacked in order to get a background image or other means to work when the text size is increased/decreased. However if you’re looking to keep fixed width columns in px sizes then I would recommend using a background image to give the illusion. If JavasScript is disabled in a user’s browser the columns not aligning break the design which is just not good enough. It has to align at the bottom of the columns regardless of platform and technology. I don’t think a small amount of CSS telling the background to repeat on a y-axis ever hurt anyone.

  20. On April 20, 2009
    11:37PM

    SohoInteractive said:

    works consistently on all browsers. Thank you for sharing.
    K.

  21. On April 27, 2009
    3:18PM

    Eric Sender said:

    You’re a genius, thanks!

  22. On April 30, 2009
    4:54AM

    Alexandru Dinulescu said:

    Hello.

    I think you are doing something very wrong with that $(document).ready() part. Since what you do is you put each variable separately instead of them together, so if you look at how the initial function is built, in the document ready you assign each variable to a DIFFERENT instance of the initial function instead of passing all the values through 1 function.

    For Ex:
    $(document).ready(function() {
    equalHeight($(”.recent-article”));
    equalHeight($(”.footer-col”));
    });

    these 2 values are independent from one another, so nothing will be compared between them. first the equalHeight function parses the recent article value, and then it passes the footer-col value but it doesnt compare it. This happened to me today while i was struggling to see why it doesnt work and it just hit me.

    In order to make it work you have to make it like this
    $(document).ready(function(){
    equalHeight($(”#left, #center, #right”));
    })
    because there is only 1 INSTANCE of the equalHeight, and all the variables are separated by commas. Each function from what i can remember separates the values by commas. Now the function will work 100%.

    It may be an oversight but i tested it and this is the result i came across.

    Best Regards
    AlexD

  23. On April 30, 2009
    9:33AM

    Rob Glazebrook said:

    Hi Alexandru,

    You’re right — if you want to compare two items/groups and equalize heights across them, you’d want to include them in a comma-delimited list like you have in your example.

    My example was looking at a slightly different use-case. In my example, I had two different groups of columns that needed to be equal heights.

    In my example, my “.recent-article” was class applied to four divs, and my “.footer-col” class applied to three divs. I needed all the recent articles to be the same size, and all the footer columns to be the same size, but I didn’t want or need my recent articles to be the same size as my footer columns. So I called the two groups of columns independently, running the function twice.

    So to clarify, if you call the function twice, nothing will be compared between the two instances. This may or may not be what you are looking for. :)

  24. On April 30, 2009
    10:24AM

    Alexandru Dinulescu said:

    Hello.

    Yes i presumed as much however you may want to edit your blog and place this bit of information in it, because most people who read this arent very proeficient in jQUery and they may just see what you did there and try to emulate that using the method you had applied and making them like that.

    My opinion at least.
    However it’s a good thing, i’ve used something very similiraly for quite a while and i just realized when i read this topic what the issue actually was.

  25. On May 08, 2009
    6:58AM

    Jeff said:

    @Rob - Thanks for the script! Although I am having trouble with it. I know very little about JS and jQuery, so I’m not the best person to troubleshoot it. I’ve got a page that’s about a 300k load. When I clear my cache and load it the first time, the script calculates well short of the highest column height and then breaks the layout by shortening both columns too much. If I hit refresh, it works beautifully. So it seems like there’s an issue with it not getting all the elements on the page loaded. I wish I could show you an example but I’m developing NDA stuff on an internal network, so…

  26. On May 08, 2009
    7:32AM

    Rob Glazebrook said:

    Hi Jeff,

    You might need to wait until the page has completely loaded before firing the script. The easiest way to do that is instead of enclosing the entire thing in this:

    $(document).ready(function() {…everything here… });

    Try using this instead:

    $(window).load(function() { …everything here… });

    The downside to this is your columns won’t adjust until everything else on the page has loaded. The upside is, your columns should be the same size.

  27. On May 08, 2009
    7:45AM

    Jeff said:

    Excellent. Works like a charm.

    I figured it was something with the page loading, but I didn’t know how to delay the calculation (like I said, I know next to nothing about JS).

    Thanks so much for your help!

  28. On May 16, 2009
    6:28PM

    richard said:

    Found this very useful, worked it into a theme, thanks!

  29. On June 04, 2009
    8:22AM

    Paul Boutin said:

    What happens if you have images in your columns?

    In jQuery running this function in the ready state of the document is before images are loaded and their heights will not be taken into account. Once the images load your column heights will no longer be equal.

  30. On June 04, 2009
    8:44AM

    Rob Glazebrook said:

    Hi Paul,

    That is true — images can cause the script some problems. There are two known (and relatively simple) ways around this problem.

    1. Instead of running the script within $(document).ready(), run it in a $(window).load() instead. Whereas document ready fires as soon as all the code is done downloading (but possibly before the images have finished), window load doesn’t fire until even the images are downloaded, allowing the script to make more accurate calculations.

    2. If you set a height attribute on your images, that height is used when calculating the overall column height, thus getting around the problem. I realize that width and height aren’t really recommended on images anymore (I’m pretty sure they’re deprecated in XHTML), but I’m personally fond of them and still use them — it prevents your content from re-wrapping once your images have downloaded.

    Enjoy!

  31. On June 08, 2009
    12:30PM

    Ben said:

    Awesome, solved a big issue with our new website design.

    Thanks a Ton!

22 Responses Elsewhere

  1. On December 08, 2008
    10:18AM

    Equal Height Columns with jQuery on Link Archive said:

    [...] Creating equal-height columns with CSS is sometimes a bear. But who needs the hassle of faux columns, “clear” divs and the rest? With this bit of jQuery, you can easily equalize the heights of any group of elements.DIRECT LINK » [...]

  2. On December 08, 2008
    11:48AM

    CSSKarma.com » This Week in Links 12/2 said:

    [...] Equal Height Columns with jQuery [...]

  3. links for 2008-12-10 « Brent Sordyl’s Blog said:

    [...] Equal Height Columns with jQuery Creating equal-height columns with CSS is sometimes a bear. But who needs the hassle of faux columns, “clear” divs and the rest? With this bit of jQuery, you can easily equalize the heights of any group of elements. (tags: jQuery css) [...]

  4. The EqualHeights jQuery Plugin said:

    [...] I wrote and published my last article on writing a function to equalize heights in jQuery, I realized that the function would probably make a really useful jQuery plugin. This is that [...]

  5. On December 11, 2008
    11:53AM

    robert haverly » Equal Column Heights With jQuery said:

    [...] columns to be equal height. After I wrote and published my last article on writing a function to equalize heights in jQuery, I realized that the function would probably make a really useful jQuery plugin. This is that [...]

  6. JQuery Custom Plug-in: Equal Height Columns :: Brenelz's Web Development Tips :: Winnipeg Web Development said:

    [...] Please visit, CSSNewbie to get another similar approach. Some ideas were taken, but I have implemented it as a [...]

  7. rascunho » Blog Archive » links for 2008-12-11 said:

    [...] Equal Height Columns with jQuery Creating equal-height columns with CSS is sometimes a bear. But who needs the hassle of faux columns, “clear” divs and the rest? With this bit of jQuery, you can easily equalize the heights of any group of elements. (tags: http://www.cssnewbie.com 2008 mes11 dia11***** equal_height layout jQuery plugin) [...]

  8. 夜游长空 » links for 2008-12-18 said:

    [...] Equal Height Columns with jQuery (tags: webdev jquery css webdesign javascript) [...]

  9. [Web] 連結分享 « 網站製作學習誌 said:

    [...] Equal Height Columns with jQuery [...]

  10. The EqualHeights jQuery Plugin | Castup said:

    [...] I wrote and published my last article on writing a function to equalize heights in jQuery, I realized that the function would probably make a really useful jQuery plugin. This is that [...]

  11. Very quick equal-height columns in jQuery » Broken Links said:

    [...] about this, and I’m certainly not claiming to have invented the technique (there’s another version here, for example); I provide it here only as an example of how jQuery makes layout problems easy [...]

  12. Spartan-Code» Blog Archive » Columnas de igual tamaño con jquery said:

    [...] información en “Equal Height Columns with jQuery” This entry was written by Pirata21 and posted on February 10, 2009 at 7:57 pm and filed under [...]

  13. On March 12, 2009
    3:33AM

    8 awesome JQuery tips and tricks said:

    [...] Source: Equal Height Columns with jQuery [...]

  14. On April 15, 2009
    4:08PM

    stign.no | Floating boxes with equal heights said:

    [...] I wrote and published my last article on writing a function to equalize heights in jQuery,I realized that the function would probably make a really useful jQuery plugin. This is that [...]

  15. On May 06, 2009
    9:47PM

    Richard Chiriboga » jQuery plug-in roundup May 2009 - Quick List said:

    [...] Equal Height Columns with jQuery [...]

  16. On May 18, 2009
    11:26PM

    Useful and Handy jQuery Tips and Tricks « Online Free Application Software Tips Tools Wallpapers said:

    [...] I think this script is quite useful. I haven’t have a chance to use it yet. It’s more on design. If you want columns have the same height, this function will answer your request. Inspired by CSSNewbie [...]

  17. On June 13, 2009
    9:12AM

    Useful and Handy jQuery Tips and Tricks « Dogfeeds——IT Telescope said:

    [...] If you want columns have the same height, this function will answer your request. Inspired by CSSNewbie view plaincopy to [...]

Leave a Comment