treehouse : what would you like to learn today?
Web Design Web Development iOS Development

Problem with Equal Height Blocks in Rows

  • Hello. I love this Equal Height Blocks in Rows article so much so that I incorporated it into my template here http://www.deepbass.com/mt-test/

    It was mostly working quite well with a couple issues that follow but for some reason the second row of blocks is now adopting the height of the first row (as you can see I added a load of filler copy to test this). Any ideas as to why this might be happening?

    The other issues are; sometimes when the page loads the longest copy is spilling outside the bottom of the container slightly. In IE6 it takes interaction with something on the page like the expanding div example at the bottom to trigger the boxes to redraw to the right height.

    Any help would be greatly appreciated!
  • Anyone? This is driving me nuts.
  • It looks like the problem is that the ".equal" class is being used for equalizing instead of ".grid_3" and ".grid_4" separately.

    Also, you could try using the code below instead... it's much more efficient and it's from the jQuery map function page (last demo):
    $.fn.equalizeHeights = function(){
    return this.height( Math.max.apply(this, $(this).map(function(i,e){ return $(e).height() }).get() ) );
    }
    $('.grid_3').equalizeHeights();
    $('.grid_4').equalizeHeights(); // don't combine this line with the above, or all of the columns will have equal heights again.
  • Hey, thanks for that Mottie! That does look a lot more efficient. The only thing is that I thought Chris' script made it so that you didn't have to assign a unique class for each row you wanted to equalize which is part of the attraction. Also, I'm not sure if you noticed or not, there's another set of boxes further down the page that are equalizing correctly to the height of their content independent from the first two rows as well as those in the footer.
  • OK, another strange turn of events. In my experimentation I simply added an ".equal" class to the next row, the ".grid_12" rounded box that follows immediately after the first four equal ".grid_3"s, and everything works fine. In another experiment I added an additional row of ".grid_3"s with different height content right after the first 4 and everything worked fine. Why then, in its current state, are the first 4 ".grid_3"s affecting the row of 2 ".grid_4"s?

    It doesn't make any sense.
  • OK, not sure what the problem is with this... but we still have the other issue with the content in the equal height blocks overflowing the containers because I don't think the padding on the containers is being taken into account when the height calculation is being done.

    In one of the comments in the original article Tom says...

    "Use “outerHeight” instead to get the correct dimensions for elements with padding/margin.

    http://api.jquery.com/outerHeight/"

    but I have no idea what would need to change in the original script for this to work.
  • Hi Fatbat!

    Hey sorry about not getting back to you... been busy with other stuff. Try this... basically I changed the "topPosition" from getting the "position" to getting the "offset" which makes a difference when the page is taller than the window.
    // equal columns
    var currentTallest = 0,
    currentRowStart = 0,
    rowDivs,
    $el,
    topPosition = 0;
    $('.equal').each(function() {
    $el = $(this);
    topPosition = $el.offset().top;
    if (currentRowStart != topPosition) {
    // we just came to a new row, set all the heights on the completed row
    if (rowDivs) { rowDivs.height(currentTallest); }
    // set the variables for the new row
    rowDivs = $el; // start new row
    currentRowStart = topPosition;
    currentTallest = $el.height();
    } else {
    // another div on the current row, add it to the list and check if it's taller
    rowDivs = rowDivs.add($el);
    currentTallest = Math.max(currentTallest, $el.height());
    }
    // do the last row
    if (rowDivs) { rowDivs.height(currentTallest); }
    });


    I'll work on making this into a plugin soon too :P
  • Sorry, hadn't checked back for answers for a few days. Thanks for this Mottie! I'll give it a try and report back asap.
  • OK, so that seems to have fixed the problem with the random row of columns further down the page taking on the height of the first row of columns, which is great.

    All that's left now is the random overflowing of the content in the .even boxes. Sometimes it's fine, sometimes it's not and hitting reload produces different results.
  • Ok so now try to change the height to outerHeight or just remove the margin and padding from the ".equal" class.

    Change
    $el.height();
    to
    $el.outerHeight();

  • I need to check back more often. Thanks for your help Mottie.

    Adding the outer height doesn't solve the problem though, it still sometimes works properly and sometimes doesn't. Loading the page might work fine the first time, reloading the page might produce an overflow 5 times in a row, and the 6th reload it goes back to working properly... or vice versa. I'm not sure why this is? I also can't think of an easy way to take the margin and padding off the ".equal" class.
  • Hi Fatbat!

    Actually after double checking, innerHeight would be more appropriate and I think that maybe you didn't change both heights in the code? Try this:
    // equal columns
    var currentTallest = 0,
    currentRowStart = 0,
    rowDivs,
    $el,
    topPosition = 0;
    $('.equal').each(function() {
    $el = $(this);
    topPosition = $el.offset().top;
    if (currentRowStart != topPosition) {
    // we just came to a new row, set all the heights on the completed row
    if (rowDivs) { rowDivs.height(currentTallest); }
    // set the variables for the new row
    rowDivs = $el; // start new row
    currentRowStart = topPosition;
    currentTallest = $el.innerHeight();
    } else {
    // another div on the current row, add it to the list and check if it's taller
    rowDivs = rowDivs.add($el);
    currentTallest = Math.max(currentTallest, $el.innerHeight());
    }
    // do the last row
    if (rowDivs) { rowDivs.height(currentTallest); }
    });
  • Hi Mottie. Yeah, I did change the heights in both places. outerHeight and innerHeight produce similar results in that the box still has variable results when you load the page and hit reload over and over again. innerHeight produces a taller box when it's working correctly, but when it overflows the result is the same visually. With outerHeight the script calculates the correct height of the first tall equal box at 1701px and when it calculates the wrong height it's 1596px. With innerHeight the script calculates the correct height at 1741px and the wrong height at 1636px.

    When an incorrect result happens, only the first two rows of ".equal" blocks overflow, the last row is shorter than it's supposed to be but doesn't overflow (it's just missing it's bottom padding). This is sort of like the first problem that affected only the first two rows leaving the third row functioning correctly.

    Any thoughts? I've uploaded the current iteration using outerHeight which when producing the right result is the most visually correct representation of the padding.

  • Something else that I have noticed... it seems the calculations work on the first load of the page and reloads cause the overflow. Forcing a refresh produces the correct result and then a reload breaks it again.
  • Oh, and for the record, I did try removing all padding and margin from the ".equal" items and the variable result still happens.
  • Hmm, ok try wrapping just that code in a
    $(window).load(function(){
    /* code here */
    });
    instead of a document ready - and btw when I test it on my desktop with document ready it never messes up the padding, so maybe it has something to do with images (but I don't see any except in the background)? That's why I'm getting you to try the window load.
  • Woohoo... that appears to have fixed it! Might be slower to draw the equal height columns maybe? A bit of "fouc" before the columns draw to the right heights. Nevertheless the problem seems solved for now. You were saying something about a plugin? Have you got a blog or website?

    Thanks a lot for your help!
  • YAY!

    Yeah I don't post on it very often, but here is my blog and here is my github.
  • @Fatbat: Ok, I finally fixed all the bugs and made a github repository, and named it Equalizer. Check it out :P
  • Oh hai, I seriously need to check back here more often. I'll scope your blog, git and the plugin. Thanks!
  • Hey Mottie. You still around? Have you done anything with this script to make it responsive? I've tried messing about with (window)resize a bit with it but haven't had a lot of success. Drop me a line if you're around.

  • I used to be a die hard ie6/7 fixer. They are dead now. Time to move on

  • Nothing about my last post had anything to do with IE6 or 7, but I'm going to guess you didn't get past the first post from a year and a half ago before telling me what you think about legacy browser support. I actually want to know how we can make this script responsive. Unfortunately it looks like Mottie has removed it from his repository altogether. But hey, thanks anyways!

  • Hey @Fatbat!

    Sorry the repo has actually moved over to the CSS-Tricks organization - Equalizer.

  • Hey @Mottie :) Thanks so very much for the direction and it's nice to see it's still being updated! Good stuff.

  • @Mottie, well that sure got a whole lot more complex since last I looked at it! The wrapper thing is different, but workable. There is one problem I'm having now though and that is with vertical centering. Using the css tables technique inside one of the equal columns...

      .something-semantic {
         display: table;
         width: 100%;
      }
      .something-else-semantic {
         display: table-cell;
         text-align: center;
         vertical-align: middle;
      }
    

    I don't think this works anymore because the content inside the equal column is getting wrapped in a span but I'm not completely sure :(

  • @Mottie, don't know if you saw this post http://css-tricks.com/forums/discussion/comment/85487#Comment_85487 but I quite like the script that @jurotek and @joshuanhibbert came up with. I have a couple issues with it though. It doesn't properly resize the columns at a breakpoint other than the one declared in the script and it can't do multiple independent rows of different heights unless each row has its own class. However, other than those two things, it's quite light and small, and seems to work quite well with getting the heights set accurately. ".equal" divs can be nested and I can also vertically center content in a row using the method above. What I would love is to figure out the most is how to get it to do multiple rows independent of one another without having to declare separate classes for each row. Any chance you might be able to have a look at it @Mottie?