Equal Height Rows for Fluid Width Elements

2019-02-07 06:33发布

问题:

I've used Chris Coyiers Equal Height Blocks in Rows jQuery script many times before, and it's always worked great.

That being said, I've always developed websites built for a specific resolution. This time around I'm developing a responsive website and main container has a fluid width. As such, I've encountered an issue and can't find a solution to my problem.

In his post, Chris says this about fluid widths:

What About Fluid Width? One of the main points of not using a table for this is that floated divs can rearrange themselves based on the available horizontal space, which is nice for fluid width. We can adjust the above code to deal with that as well. Basically the first time this is run we'll measure the height of each block and remember it with jQuery's data() method. Then when the window is resized, run the code again but use the original size to adjust the rows, not the new size.

Note that he's specifically referencing a fluid width container. In my case it's not just the container, but the child elements that also have fluid widths. The very blocks that I need to equalize are the same blocks have fluid widths and adjust to the resolution of the window/container.

I believe that because the element's 'originalHeight' changes with the container size, the script will no longer work properly.

My speculation may be wrong, but one way or another this isn't working with fluid width elements. Looking for some help!

Of course, here's a jsfiddle I created to demonstrate the problem. Just resize the width of the window and you'll notice the heights of the containers do not update.

I'm running the following code to call the function on the window resize event:

$(window).resize(function() {
    columnConform();
});

Thanks in advance

回答1:

You're only equalizing the heights of columns that exist on one row so you could replace all that JS with this

$.fn.extend({
    equalHeights: function(options){
      var ah=(Math.max.apply(null, $(this).map(function(){ return $(this).height(); }).get()));
      if (typeof ah=='number') $(this).height(ah);
    }
 });

and execute like so

$(document).ready(function() {
    $(window).resize(function() {
        $('.equalize').equalHeights();
    }).trigger('resize'); // don't write code twice just to execute on page load - trigger the event you just bound to instead

})

But if you want to do it per pseudo row working demo

<ul class="eqme">
  <li><h1>One</h1></li>
  <li><h2>Two</h2></li>
  ....
</ul>

JS

$.fn.extend({
equalHeights: function(){
    var top=0;
    var classname=('equalHeights'+Math.random()).replace('.','');
    $(this).each(function(){
      if ($(this).is(':visible')){
        var thistop=$(this).offset().top;
        if (thistop>top) {
            $('.'+classname).removeClass(classname); 
            top=thistop;
        }
        $(this).addClass(classname);
        $(this).height('auto');
        var h=(Math.max.apply(null, $('.'+classname).map(function(){ return $(this).outerHeight(); }).get()));
        $('.'+classname).height(h);
      }
    }).removeClass(classname); 
}       

});

$(function(){
  $(window).resize(function(){
    $('.eqme li').equalHeights();
  }).trigger('resize');
});

This will even take care of many elements that are the children of the same parent even if they break row, e.g. a ul containing 100 li elements when only 10 fit on one row, or when the li width is static but the page width is not, on resize they'll clear onto new lines when the window is shrunk (or float back to the one above if expanding the width) then their heights will fix to suit the tallest per pseudo row.

Notes:

Feedback suggests that outerHeight() works better than .height() in some situations.

In production, within the window.resize function, I added a clearTimeout and setTimeout of 100ms before reacting to the change of size to prevent slowdown when resizing by dragging a corner.



回答2:

Assuming I understood your question, this code should work:

$(document).ready(function() {

    $(window).on('resize', function() {
        $('.equalize').css('height', highest($('p')));
    }).trigger('resize');

});

function highest(el) {
    var highest = 0;
    el.each(function() {
        var height = $(this).height();
        if(height > highest) {
          highest = height;
        }
    });
    return highest;   
}

Fiddle