Setting dynamic, equal heights for multiple elements with jQuery


Birds of different heights

The goal: Dynamic, equal heights

Sometimes you’d like to have several elements that will all be the same height, no matter what content they have inside them. In other words:

Variable height content boxes

You don’t want this

Equal height content boxes

You want this

This is devilishly hard with straight CSS (if you’re not using tables, which you generally shouldn’t be for layout).

But it’s pretty easy with JavaScript/jQuery. Here’s a demo!

How to do it

Here’s the code:


(function($){
	function equalizeHeights(selector) {
		var heights = new Array();

		// Loop to get all element heights
		$(selector).each(function() {

			// Need to let sizes be whatever they want so no overflow on resize
			$(this).css('min-height', '0');
			$(this).css('max-height', 'none');
			$(this).css('height', 'auto');

			// Then add size (no units) to array
	 		heights.push($(this).height());
		});

		// Find max height of all elements
		var max = Math.max.apply( Math, heights );

		// Set all heights to max height
		$(selector).each(function() {
			$(this).css('height', max + 'px');
		});	
	}

	$(window).load(function() {
		// Fix heights on page load
		equalizeHeights(MYSELECTOR);

		// Fix heights on window resize
		var iv = null;
		$(window).resize(function() {

			if(iv !== null) {
				window.clearTimeout(iv);
			}

			// Needs to be a timeout function so it doesn't fire every ms of resize
			iv = setTimeout(function() {
	      			equalizeHeights(MYSELECTOR);
			}, 120);
		});
	});
})(jQuery);

You’ll need to change ‘MYSELECTOR’ above to whatever CSS selector defines all the elements whose heights you want to equalize (most likely a class, like .content-block).

Once you’ve done that, save the code as a .js file, drop it in anywhere on the page after jQuery is loaded, and you’re ready to go!

Notes

  1. Other, very similar solutions exist—here’s one. The major difference is that the solution presented here fires automatically on page load and window resize, rather than needing to be called manually.
  2. The function first fires directly after the window finishes loading, meaning that items may “flicker” from different sizes to the same size. Unfortunately, $(document).ready won’t work, because the items may not have heights yet.
  3. The function will also fire anytime the user resizes his or her screen, meaning that items stay the same height even as lines break differently.
  4. If box-sizing is set to border-box (which we recommend), you’ll need to rework this code to add each element’s vertical border and padding to its height—or else the tallest element will overflow by the amount of its vertical borders + vertical padding.

Enjoy!

Hope the script works for you! Would love to hear questions or comments.

Image Credits: Paul and Jill

12 thoughts on “Setting dynamic, equal heights for multiple elements with jQuery

  1. Deepak Pradeep

    Thank you so much! I’ve been breaking my head over this. This is the easiest solution I could find for my WordPress site using Foundation Zurb (Foundation’s own Equalizer didn’t seem to work).

    Reply
  2. Jeff Wright

    What if I want to have multiple rows of content resize with varying heights, is there a way to do that without having to duplicate the script? I assume I can’t use the same class as it will give both rows the same height.

    Reply
    1. Fred Meyer Post author

      Hi Jeff,

      Great question. If I’m understanding you properly, you actually only need to duplicate the function call for each row and the script will work as you like; it calculates new heights each time the function is called.

      The solution you’re after would look like:

      $(window).load(function() {
      // Fix heights on page load
      equalizeHeights(SELECTOR1);
      equalizeHeights(SELECTOR2);

      // Fix heights on window resize
      $(window).resize(function() {

      // Needs to be a timeout function so it doesn't fire every ms of resize
      setTimeout(function() {
      equalizeHeights(SELECTOR1);
      equalizeHeights(SELECTOR2);
      }, 120);
      });
      });

      Or slightly more elegant would be:

      $(window).load(function() {
      // Fix heights on page load
      equalizeAllHeights();
      equalizeAllHeights();

      // Fix heights on window resize
      $(window).resize(function() {

      // Needs to be a timeout function so it doesn't fire every ms of resize
      setTimeout(function() {
      equalizeAllHeights();
      equalizeAllHeights();
      }, 120);
      });
      });

      function equalizeAllHeights() {
      var selectors = [SELECTOR1, SELECTOR2]
      $(selectors).each(function(index, item) {
      equalizeHeights(item);
      });
      }

      I haven’t tested that second way of doing it, so let me know if it’s buggy and I’ll try to fix.

      Reply
  3. Jeff+Wright

    How about multiple rows with different heights? Is there a way to do this without having to use the same function multiple times?

    Reply
  4. Torben

    Hello, this is rather old but I just found this.

    Notice that the timeout at the end doesn’t throttle the calls, it just sets them to execute in 120ms. You’ll still have the same amount of calls to equalizeAllHeights(), they just kick in 120ms later (but after 120ms you notice no difference in delay)

    To make it work, save the timeout ID and clear it before each setTimeout

    var iv = null;
    $(window).resize(function() {

    if (iv)
    window.clearTimeout(iv);

    iv = window.setTimeout(equalizeAllHeights, 120);
    });

    This would actually make sure that resizing in a 120ms frame you’ll only get once call. Only after 120ms the handler is fired once.

    Reply
    1. Fred Meyer Post author

      Hi Torben,

      Wow, you’re absolutely right! I’ve altered the code to reflect your fix.

      Thanks so much for writing!

      Fred

      Reply
  5. Simon Clay

    Hi,
    Thanks, this works really well.
    How can I stop the equal height kicking in when the browser width is less than 768px?

    Reply
  6. Jordan

    @Simon Clay

    I’d try wrapping the equalizeHeights(MYSELECTOR) functions in an if statement to check if window width is greater than 768px.

    Something like:

    if ( $(window).innerWidth() > 768 ) ){
    equalizeHeights(MYSELECTOR);
    };

    Reply

Leave a Reply

Your email address will not be published.