最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using jQuery to make multiple elements on a page the same height - Stack Overflow

programmeradmin5浏览0评论

I have a function I'm using to make any elements on a page with the class equalheight all the same height (the height of the tallest element):

equalheight = function(container){

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

    $(container).each(function() {
        $el = $(this);
        $($el).height('auto')
        topPostion = $el.position().top;

        if (currentRowStart != topPostion) {
            for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
                rowDivs[currentDiv].height(currentTallest);
            }
            rowDivs.length = 0; // empty the array
            currentRowStart = topPostion;
            currentTallest = $el.height();
            rowDivs.push($el);
        } else {
            rowDivs.push($el);
            currentTallest = (currentTallest < $el.height()) ? ($el.height()) : (currentTallest);
        }
        for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
            rowDivs[currentDiv].height(currentTallest);
        }
    });
}

$(window).load(function() {
    equalheight('.equalheight');
});

$(window).resize(function(){
    equalheight('.equalheight');
});

The problem I'm running in to is that, let's say I have two rows of boxes. The first row I want all to be the same height, so I give them the class equalheight. Okay. Good. Now, I also want the second row of boxes to be all the same height, but just of those boxes in the second row.

Is there any way I can modify this code to allow me to set equal height of multiple groups of elements? For example, maybe something like setting the class as equalheight1, equalheight2, etc.?

EDIT: One thing I thought about was adding a data attribute on to each element and just calculate the tallest element for each element with the same data attribute..? Like:

<div class="equalheight" data-equalgroup="1"> </div>

I have a function I'm using to make any elements on a page with the class equalheight all the same height (the height of the tallest element):

equalheight = function(container){

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

    $(container).each(function() {
        $el = $(this);
        $($el).height('auto')
        topPostion = $el.position().top;

        if (currentRowStart != topPostion) {
            for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
                rowDivs[currentDiv].height(currentTallest);
            }
            rowDivs.length = 0; // empty the array
            currentRowStart = topPostion;
            currentTallest = $el.height();
            rowDivs.push($el);
        } else {
            rowDivs.push($el);
            currentTallest = (currentTallest < $el.height()) ? ($el.height()) : (currentTallest);
        }
        for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
            rowDivs[currentDiv].height(currentTallest);
        }
    });
}

$(window).load(function() {
    equalheight('.equalheight');
});

$(window).resize(function(){
    equalheight('.equalheight');
});

The problem I'm running in to is that, let's say I have two rows of boxes. The first row I want all to be the same height, so I give them the class equalheight. Okay. Good. Now, I also want the second row of boxes to be all the same height, but just of those boxes in the second row.

Is there any way I can modify this code to allow me to set equal height of multiple groups of elements? For example, maybe something like setting the class as equalheight1, equalheight2, etc.?

EDIT: One thing I thought about was adding a data attribute on to each element and just calculate the tallest element for each element with the same data attribute..? Like:

<div class="equalheight" data-equalgroup="1"> </div>
Share Improve this question edited Aug 17, 2015 at 13:40 MultiDev asked Aug 17, 2015 at 13:35 MultiDevMultiDev 10.6k26 gold badges82 silver badges154 bronze badges 2
  • I think you're close, but will need to define a row class, so you can select groups of .equalHeight objects, rather than all of them at once. It should be simple to define a container as equalHeightRow, and then only run the code for each set. – wwwmarty Commented Aug 17, 2015 at 13:40
  • What if, after re-size one div fall down, you want that div have the same height as the above row? – Taher Rahgooy Commented Aug 17, 2015 at 14:18
Add a ment  | 

8 Answers 8

Reset to default 5

We iterate through all elements and add them to the currentRow columns, and updating the maximum height. When we reach an element that its top differs from previous one, we update all heights of currentRow columns and then we set currentRow to a new one, finally after exiting from the loop, we update the last row columns' height.

equalheight = function (container) {
  var currentRow = { cols: [], h: 0 };
  var topPostion = -1;
  $(container).each(function () {
       var $el = $(this);
       $($el).height('auto')
       if (topPostion != $el.position().top) {
            for (var j = 0; j < currentRow.cols.length; j++) {
                currentRow.cols[j].height(currentRow.h);
            }
            topPostion = $el.position().top;
            currentRow = { cols: [], h: 0 };
        }
        currentRow.cols.push($el);
        if ($el.height() > currentRow.h) {
            currentRow.h = $el.height();
        }

  });
  for (var j = 0; j < currentRow.cols.length; j++) {
       currentRow.cols[j].height(currentRow.h);
  }
}
$(window).load(function() {
     equalheight('.equalheight');
});

$(window).resize(function(){
    equalheight('.equalheight');
});     

here is a fiddle for it.

As far as I can tell you should be able to give each row a different class and simply run the function on each row;

$(window).load(function() {
    equalheight('.equalheight-row-1');
    equalheight('.equalheight-row-2');
});

$(window).resize(function(){
    equalheight('.equalheight-row-1');
    equalheight('.equalheight-row-2');
});

Although, looking closer at the code it seems to actually take care of that itself (with the currentRow stuff).

Edit: You don't actually have to give each row a different class, just do this;

$('.equalheight-row').each(function () {
    equalheight($(this));
});

And the function should run individually on each row.

Looks to me it should be as simple as just adding it to the load and resize functions:

$(window).load(function() {
    equalheight('.equalheight1');
    equalheight('.equalheight2');
});

$(window).resize(function(){
    equalheight('.equalheight1');
    equalheight('.equalheight2');
});

Just note the classname.

You could add a second class to the divs you want to group up. Something like:

<div class="equalheight first"></div>
<div class="equalheight first"></div>
<div class="equalheight second"></div>
<div class="equalheight second"></div>

And then in your javascript:

$(window).load(function() {
    equalheight('.first.equalheight');
    equalheight('.second.equalheight');
});

You could fix this using flexbox layout, if your target doesn't require IE8 or older.

HTML

<div class="rows">
    <div class="cell">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Necessitatibus illo quibusdam, perspiciatis vel officiis alias autem consequuntur labore mollitia omnis natus, fuga, illum id deleniti assumenda amet harum deserunt cum.</div>
    <div class="cell"><div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid provident, quaerat ducimus perspiciatis omnis sint aspernatur quibusdam saepe, quam similique eligendi nisi nesciunt atque laudantium quidem, doloribus culpa deserunt laboriosam.</div>
    <div>Aspernatur porro vitae beatae nam fuga nisi magni eaque modi odio voluptate veritatis laboriosam animi, ullam optio quidem sequi ducimus voluptas quaerat adipisci dignissimos. Velit sequi mollitia nemo veritatis optio.</div></div>
    <div class="cell">Voluptate suscipit, laudantium. A, veniam repellat iste eligendi magnam at nisi quod suscipit laudantium tenetur porro accusamus quam quae nulla voluptatibus molestiae quisquam quos doloremque dolorum ipsam rem. Non, sunt.</div>
    <div class="cell">Tempore praesentium voluptas earum harum numquam consequatur modi omnis, debitis fuga suscipit, quae repellat hic iure molestiae doloribus. Eveniet voluptate quam placeat fugit iusto consequatur nam eaque porro eligendi itaque.</div>
    <div class="cell">Sed deleniti ullam iusto pariatur natus, voluptatibus iste, ipsum assumenda dolor provident vel eum quisquam odit placeat in eligendi! Doloremque corporis maxime non culpa iusto rerum incidunt excepturi illum veniam.</div>
    <div class="cell">Ullam provident fuga doloremque beatae possimus, facilis veritatis quae officia ut, atque expedita qui nulla adipisci, voluptate quas ipsam dolore vel architecto sapiente tenetur tempora laborum blanditiis libero. Saepe, ad!</div>
    <div class="cell">Molestiae quam impedit sequi suscipit, rerum hic quia saepe excepturi, in assumenda inventore maxime vero. Earum aperiam dicta aut voluptas, rerum, repudiandae modi deserunt minima nostrum recusandae sequi, sunt natus!</div>
</div>

CSS

.rows {
    margin: 15px auto;
    width: 960px;
    padding: 15px;
    border: 1px solid;
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-flex-wrap: wrap;
            -ms-flex-wrap: wrap;
                    flex-wrap: wrap;
}

.cell {
    min-width: 270px;
    max-width: 275px;
    -webkit-box-flex: 1;
    -webkit-flex: 1;
            -ms-flex: 1;
                    flex: 1;
    padding: 15px;
    border: 1px solid #F0F0F0;
    margin: 7.5px;
}

demo: http://codepen.io/pjetr/pen/wabJYe

One of the efficient ways to achieve what you want is to divide your task in two functions.

  1. Set heights of boxes according to rows in one function
  2. Give class names to rows (like equalheight1, equalheight2..) based on top offset in another function.

JS:

$(document).ready(function () {
    equalheight = function () {
        var rowIndex = 1;
        while ($('.equalheight' + rowIndex ).length) {
            var currDivs = [];

            $('.equalheight' + rowIndex ).each(function () {
                currDivs.push($(this).height());
            });

            var maxHeight = Math.max.apply(Math, currDivs);

            $('.equalheight' + rowIndex).each(function () {
                $(this).height(maxHeight);
            });
            rowIndex++;
        }
    };

    assignRows = function () {
        // Reassign classes based on top offset
        var allBoxes = $('.equalheight');
        allBoxes.removeClass();
        var rowIndex = 1;
        var currentRowTop = 0;
        var rowMap = {};

        for (var i = 0; i < allBoxes.length; i++) {
            if (rowMap[$(allBoxes[i]).position().top] === undefined)
                rowMap[$(allBoxes[i]).position().top] = [];
            rowMap[$(allBoxes[i]).position().top].push(allBoxes[i]);
        }

        for (var row in rowMap) {
            for (var i = 0; i < rowMap[row].length; i++) {
                $(rowMap[row][i]).addClass('equalheight equalheight' + rowIndex);
            }
            rowIndex++;
        }
    };

    assignRows();
    equalheight();

    $(window).resize(function () {
        assignRows();
        equalheight();
    });
});

In HTML, all boxes would have same class equalheight. For example:

<div class="equalheight">Element1</div>
<div class="equalheight">Element2</div>
<div class="equalheight">Element3</div>

JSFiddle: https://jsfiddle/w4j7Lwap/2/

I may be going a bit too far out of your depth but if you're using jQuery, why not build a plugin like this?

I'm going to use the same name attribute method suggested by Chris Dobson

$.fn.equalHeight=function(){
    var $this=$(this);
    heights={};
    function setup(e){
        var n=$(e).attr('name');
        if(!heights[n])heights[n]=[];
        heights[n].push($(e).height());
        //console.log(heights);     
    };
    function getHighest(name){
        return Math.max.apply(null,heights[name]);
    };
    function setHeights(){
        $this.height(getHighest($this.attr('name')));
        //$this.foreach(function(){
           // $this.height(getHighest($(this).attr('name')));
       // });
    };
    $this.each(function(){
        return setup($this);//think I need a return here?
    });
    $('window').on('resize, load',function(){
       setHeights(); 
    });
    setHeights(); 
};
$(document).ready(function(){
$('.equalheight').equalHeight();

});

I also used this question to help in your answer ;)

Might want to get someone to double check it. I'm going to test it as well.

Try adding an attribute such as name* a new class to the elements - radio buttons use a similar method with the name element to determine which buttons are grouped together.

You can use then select by the equalheight class and the new class eg. equal1 to select only the elements from one group and deal with each group separately.

<div class="equalheight equal1"></div>
<div class="equalheight equal1"></div>
<div class="equalheight equal2"></div>
<div class="equalheight equal2"></div>

then in your JavaScript:

var equalGroupOne = $(".equalheight.equal1")
setHeightEqual(equalGroupOne);

var equalGroupTwo = $(".equalheight.equal2")
setHeightEqual(equalGroupTwo);

function setHeightEqual(equalGroup) {
  //Your code here...
}

*My initial answer suggested the name attribute and jQuery attributeEquals selector, but the name attribute is not appropriate for div elements. An alternate approach is to use HTML5's data-* attributes and there is an argument for this being correct, but a new class seemed more appropriate (see my ment below for more).

发布评论

评论列表(0)

  1. 暂无评论