Setting equal heights for div's with jQuery
Asked Answered
R

17

43

I want to set equal height for divs with jQuery. All the divs may have different amount of content and different default height. Here is a sample of my html layout:

<div class="container">
    <div class="column">This is<br />the highest<br />column</div>
    <div class="column">One line</div>
    <div class="column">Two<br />lines</div>
</div>
<div class="container">
    <div class="column">One line</div>
    <div class="column">Two<br>lines</div>
    <div class="column">One line</div>
</div>

I'm setting the height with the next jQuery function:

$(document).ready(function(){

    var highestBox = 0;
        $('.container .column').each(function(){  
                if($(this).height() > highestBox){  
                highestBox = $(this).height();  
        }
    });    
    $('.container .column').height(highestBox);

});

This works fine but not in my case because I want all the 'columns' equal only inside one 'container'. This means that in the first container all the boxes must be as high as the first div, but in the second one they must be equal to second column.

So question is -- how should I modify my jQuery to reach this?

Thank you!

Redemption answered 27/7, 2012 at 12:58 Comment(0)
S
107

Answer to your specific question

Your code was checking all columns within any container, what you need to do is:

  • Loop through each container
    • Get the heights of each column within that container
    • Find the highest one
    • Apply that height to every column in that container before moving on to the next one.

Note: Try to provide an example jsfiddle of your issue, it enables us to more easily help you and understand the issue, you get to see the working solution straight away and it encourages quicker responses.

Quick (Rough) Example

$(document).ready(function(){

    // Select and loop the container element of the elements you want to equalise
    $('.container').each(function(){  
      
      // Cache the highest
      var highestBox = 0;
      
      // Select and loop the elements you want to equalise
      $('.column', this).each(function(){
        
        // If this box is higher than the cached highest then store it
        if($(this).height() > highestBox) {
          highestBox = $(this).height(); 
        }
      
      });  
            
      // Set the height of all those children to whichever was highest 
      $('.column',this).height(highestBox);
                    
    }); 

});
.container { border 1px solid red; }
.column { border: 1px solid blue; float:left; width: 30%; text-align:center; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div class="container">
    <div class="column">This is<br />the highest<br />column</div>
    <div class="column">One line</div>
    <div class="column">Two<br />lines</div>
</div>
<div class="container">
    <div class="column">One line</div>
    <div class="column">Two<br>lines</div>
    <div class="column">One line</div>
</div>


Library!

Here's a library i found that looks promising if you want some more clever equalisation controls

http://brm.io/jquery-match-height-demo/



Addressing @Mem's question

Question: Will $(document).ready() work if you have images that need to load which in turn modify the heights of the containers?


Equalising heights after image load

If you are loading images, you will find that this solution doesn't always work. This is because document.ready is fired at the earliest possible time, which means it does not wait for external resources to be loaded in (such as images).

When your images finally load, they may distort the heights of their containers after the equalisation script has run, causing it too appear not too work.


Solving equalising heights with images

  1. Bind to image loading events

This is the best solution (at the time of writing) and involves binding to the img.load event. All you have to do is get a count of how many img's there are $('img').length and then for each load, -1 from that count until you hit zero, then fire the equaliser.

The caveat here is load may not fire in all browsers if the image is in the cache. Look around google/github, there should be a solution script out there. At the time of writing i found waitForImages from Alexander Dickson (untested, this is not an endorsement).

  1. Another more reliable solution is the window.load event. This should generally always work. However, if you check the docs out, you'll notice this event fires after ALL external resources are loaded. This means if your images are loaded but there's some javascript waiting to download it won't fire until that completes.

If you load the majority of your externals asyncronously and are clever with minimising, compressing and spreading the load you probably wont have any issues with this method, however a suddenly slow CDN (happens all the time) could cause issues.

In both cases, you could take a dumb approach and apply fallback timers. Have the equalise script run automatically after a set few seconds just in case the event doesn't fire or something is slow out of your control. It's not fool proof, but in reality you'll satisfy 99% of your visitors with this fallback if you tune the timer correctly.



Years later this is still getting upvotes, with flexbox widely supported these days you may want to consider just plain CSS for this, unless there's a specific reason you are using JS for it

.container {
  display: flex;
  border: 2px dashed red;
  margin: 10px 0;
}

.container > .column { 
 padding: 10px;
}

.container.fill-width {
  justify-content: stretch;
}

.container.fill-width>.column {
  flex-grow: 1
}

.container>.column:nth-child(1) {
  background: yellow;
}

.container>.column:nth-child(2) {
  background: blue;
}

.container>.column:nth-child(3) {
  background: green;
}
<div class="container">
  <div class="column">Some<br>text</div>
  <div class="column">Some<br>more<br>text<br>here</div>
  <div class="column">One line</div>
</div>
<div class="container">
  <div class="column">Some<br>more<br>even<br>longer<br>text<br>here</div>
  <div class="column">Some<br>text</div>
  <div class="column">One line</div>
</div>
<div class="container fill-width">
  <div class="column">Some<br>more<br>text<br>here</div>
  <div class="column">Some<br>text</div>
  <div class="column">One line</div>
</div>
Spaceport answered 27/7, 2012 at 13:8 Comment(6)
"a quicker answer" like quicker than 9 mins :)Banlieue
yep, had i not messed around creating a fiddle from scratch it could have been more like 5 maybe, but on a more serious note, had the javascript been more complex some people may not have even bothered to help without a fiddle as they may want to "see it in action" in order to solve it. Get people into good habits early and it helps them in the long term i suppose :)Spaceport
@Spaceport My school's internet blocks jsfiddle for some reason that I can't understand..Menken
Thats strange, might be the word "fiddle" (if you dont understand why i'm not going to explain though). If you ask them they will probably unblock it for you since its for educational purposes. But if your interested in seeing the code i posted i'll chuck it into the post above for you nowSpaceport
@Spaceport Is it just me or we both sent the exact same answer :)Menken
Will document ready work if we have images that need to adjust?Wira
M
10
$(document).ready(function(){

    $('.container').each(function(){  
        var highestBox = 0;

        $(this).find('.column').each(function(){
            if($(this).height() > highestBox){  
                highestBox = $(this).height();  
            }
        })

        $(this).find('.column').height(highestBox);
    });    


});
Menken answered 27/7, 2012 at 13:8 Comment(1)
nice timing.. I was about to post the same :)Eindhoven
E
7

You need this:

$('.container').each(function(){  
     var $columns = $('.column',this);
     var maxHeight = Math.max.apply(Math, $columns.map(function(){
         return $(this).height();
     }).get());
     $columns.height(maxHeight);
});

Explanation

  • The following snippet constructs an array of the heights:

    $columns.map(function(){
        return $(this).height();
    }).get()
    
  • Math.max.apply( Math, array ) finds the maximum of array items

  • $columns.height(maxHeight); sets all columns' height to maximum height.

Live demo

Ema answered 27/7, 2012 at 13:10 Comment(0)
B
5

Important improvement! (I added $(this).height('auto'); before measuring height - we should reset it to auto. Then we can use this function on resize)

function equalheight () {
            $('.cont_for_height').each(function(){  

                var highestBox = 0;
                $('.column_height', this).each(function(){

                    var htmlString = $( this ).html()

                    ;


                $(this).height('auto');

                    if($(this).height() > highestBox) 
                       highestBox = $(this).height(); 
                });  

                $('.column_height',this).height(highestBox);

        });  

        }
Buck answered 26/9, 2014 at 6:44 Comment(1)
Good catch!! lots of useful for dynamic content.Thorn
K
3

This is my version of setting blocks in the same hight... For example you have a divthat contains divs with the name "col"

$('.col').parent().each(function() {
    var height = 0,
        column = $(this).find('.col');
    column.each(function() {
        if ($(this).height() > height) height = $(this).height();
    });
    column.height(height);
});
Kordofanian answered 21/7, 2014 at 10:10 Comment(0)
P
2

You need imagesLoaded if the container have images inside. This works for responsive too.

$(document).ready(function () { 
     equalHeight('.column');
});
$(window).resize(function(){equalHeight('.column');});

function equalHeight(columnClass){
    $('.eq-height-wrap').imagesLoaded(function(){
        $('.eq-height-wrap').each(function(){  

            var maxHeight = Math.max.apply(null, $(this).find(columnClass).map(function ()
            {
                return $(this).innerHeight();
            }).get());

            $(columnClass,this).height(maxHeight);
        });
    });
}
Postprandial answered 14/8, 2015 at 15:38 Comment(0)
T
1

You can write the function this way also Which helps to build your code one time just to add class name or ID at the end

function equalHeight(group) {
               tallest = 0;
               group.each(function() {
                  thisHeight = jQuery(this).height();
                  if(thisHeight > tallest) {
                     tallest = thisHeight;
                  }
               });
               group.height(tallest);
            }
            equalHeight(jQuery("Add your class"));
Trusty answered 21/1, 2015 at 6:25 Comment(0)
U
1

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

 $('.blocks').each(function() {

   $el = $(this);
   topPostion = $el.position().top;
   
   if (currentRowStart != topPostion) {

     // we just came to a new row.  Set all the heights on the completed row
     for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
       rowDivs[currentDiv].height(currentTallest);
     }

     // set the variables for the new row
     rowDivs.length = 0; // empty the array
     currentRowStart = topPostion;
     currentTallest = $el.height();
     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 < $el.height()) ? ($el.height()) : (currentTallest);

  }
   
  // do the last row
   for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
     rowDivs[currentDiv].height(currentTallest);
   }
   
 });​
$('.blocks') would be changed to use whatever CSS selector you need to equalize.
Udo answered 13/2, 2015 at 8:16 Comment(0)
C
1
  <script>
function equalHeight(group) {
   tallest = 0;
   group.each(function() {
      thisHeight = $(this).height();
      if(thisHeight > tallest) {
         tallest = thisHeight;
      }
   });
   group.height(tallest);
}
$(document).ready(function() {
   equalHeight($(".column"));
});
</script>
Convulse answered 19/5, 2015 at 5:16 Comment(0)
S
1

So, below the jquery script to set the equal height to column which Math.max will calculate the two divs height and takes the highest height either it may be left or right.

$(document).ready(function() {
var Equalheights = Math.max($(“#left”).height(), $(“#right”).height());
$(“#left”). Equalheights(d);
$(“#right”). Equalheights(d);
});
Highest height will be assigned to both left and right divs

Live Demo

Shulock answered 4/7, 2018 at 13:32 Comment(0)
E
1

I wish i'd read this post before I (with help from Earl) created this one

setMaxHeightForTitles($column, $title) {
      var maxHeight = 0;
      $column.find($title)
      .each(function(index, title){
        var height = $(title).height();
        if  (height > maxHeight) maxHeight = height;
      })
      .each(function(index, title){
        $(title).height(maxHeight);
      });
  }
Emogene answered 11/1, 2019 at 17:5 Comment(0)
V
1

Here is what worked for me. It applies the same height to each column despite their parent div.

$(document).ready(function () {    
    var $sameHeightDivs = $('.column');
    var maxHeight = 0;
    $sameHeightDivs.each(function() {
        maxHeight = Math.max(maxHeight, $(this).outerHeight());
    });
    $sameHeightDivs.css({ height: maxHeight + 'px' });
});

Source

Villenage answered 27/12, 2019 at 12:59 Comment(0)
E
0

You can reach each separate container using .parent() API.

Like,

var highestBox = 0;
        $('.container .column').each(function(){  
                if($(this).parent().height() > highestBox){  
                highestBox = $(this).height();  
        }
    }); 
Eindhoven answered 27/7, 2012 at 13:3 Comment(1)
Thank you, but this doesn't work as I need. The height is the same for all six divs :(Redemption
H
0

There is a jQuery plugin for this exact purpose: https://github.com/dubbs/equal-height

If you want to make all columns the same height, use:

$('.columns').equalHeight();

If you want to group them by their top position, eg. within each container:

$('.columns').equalHeight({ groupByTop: true });
Historic answered 23/5, 2016 at 23:8 Comment(0)
M
0
function setEqualHeight(columns) {
  var tallestColumn = 0;

  columns.each(function(){
    var currentHeight = $(this).height();

    if(currentHeight > tallestColumn){
      tallestColumn  = currentHeight;
    }
  });

  columns.height(tallestColumn);
}

=> setEqualHeight($('.column'));
Misfortune answered 19/9, 2016 at 7:25 Comment(0)
S
0
// Select and loop the container element of the elements you want to equalise
        $('.equal').each(function(){  

          // Cache the highest
          var highestBox = 0;

          // Select and loop the elements you want to equalise
          $('.col-lg-4', this).each(function(){

            // If this box is higher than the cached highest then store it
            if($(this).height() > highestBox) {
              highestBox = $(this).height(); 
            }

          });  

          // Set the height of all those children to whichever was highest 
          $('.col-lg-4',this).height(highestBox);

        }); 

    });
Subterranean answered 10/4, 2017 at 14:16 Comment(0)
E
0
<div class('a')>
   <div class('.cols-to-eq')></div>
   <div class('.cols-to-eq')></div>
   <div class('.cols-to-eq')></div>
   <div class('.cols-to-eq')></div>
</div>
<div class('b')>
   <div class('.cols-to-eq')></div>
   <div class('.cols-to-eq')></div>
   <div class('.cols-to-eq')></div>
   <div class('.cols-to-eq')></div>
</div>
var a = ['.a','.b'];
a.forEach(function(value) {
    var column = 0;
    $(value).find('.cols-to-eq').each(function(){
        if($(this).height() > column){
            column = $(this).height();
        }
    });
    $(value).find('.cols-to-
    eq').attr('style','height:'+column+'px');
   });
Electrify answered 7/9, 2017 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.