Question

I know this question has been asked a million times but i'm looking for something more specific.

As my site is fully responsive I need the divs to be resized based on a per row basis rather than setting all to one height.

I am using the following modified code to set the heights of all divs within a container:

$.fn.eqHeights = function() {
    var el = $(this);
    if (el.length > 0 && !el.data('eqHeights')) {
        $(window).bind('resize.eqHeights', function() {
            el.eqHeights();
        });
        el.data('eqHeights', true);
    }
    return el.each(function() {
        var curTop = 0;
        var curHighest = 0;
        $(this).children().each(function(indx) {
            var el = $(this),
                elHeight = el.height('auto').outerHeight();

            var thisTop = el.position().top;
            if (curTop > 0 && curTop != thisTop) {
                curHighest = 0;
            }

            if (elHeight > curHighest) {
                curHighest = elHeight;
            }

            curTop = thisTop;

        }).height(curHighest);
    });
};

I have var thisTop = el.position().top; to determine which elements are on the same row but am unsure how I can then set all elements in the same row to the highest value?

Currently .height(curHighest); sets all the elements to the same height whether they are on the same row or not.

Thanks for help with this.

Was it helpful?

Solution

Managed to get this working with the following snippet:

$.fn.eqHeights = function(options) {

    var defaults = {  
        child: false 
    };  
    var options = $.extend(defaults, options); 

    var el = $(this);
    if (el.length > 0 && !el.data('eqHeights')) {
        $(window).bind('resize.eqHeights', function() {
            el.eqHeights();
        });
        el.data('eqHeights', true);
    }

    if( options.child && options.child.length > 0 ){
        var elmtns = $(options.child, this);
    } else {
        var elmtns = $(this).children();
    }

    var prevTop = 0;
    var max_height = 0;
    var elements = [];
    elmtns.height('auto').each(function() {

        var thisTop = this.offsetTop;

        if (prevTop > 0 && prevTop != thisTop) {
            $(elements).height(max_height);
            max_height = $(this).height();
            elements = [];
        }
        max_height = Math.max(max_height, $(this).height());

        prevTop = this.offsetTop;
        elements.push(this);
    });

    $(elements).height(max_height);
};

I also added the ability to specify a certain element so that this gets the height change instead.

Usage:

$('.equalheight').eqHeights();
$('.equalheight-frame').eqHeights({child:'.frame'});

OTHER TIPS

I recently had to do the same thing, this is what I ended up with:

$.fn.equalRowHeights = function() { 

    var count = this.length;

    // set element's height auto so it doesn't mess up when the window resizes
    this.height('auto');

    for (var i = 0; i < count; ) {

        // get offset of current element
        var x = this.eq(i).offset().top;

        // get elements in the same row
        var $rowEls = this.filter(function() {
            return $(this).offset().top === x;
        });

        // set the height elements in the same row
        $rowEls.height( 
            Math.max.apply(null, $rowEls.map(function() { 
                return $(this).height(); 
            }).get()); 
        );

        // set i to avoid unnecessary iterations
        i = $rowEls.filter(':last').index() + 1;    
    }

    var $this = this,
        timer = 0;

    // bind the resize event if it hasn't been added already 
    if (!$this.data('equalRowHeights')) {
        $(window).on('resize.equalRowHeights', function(e) {
            // add a buffer to prevent firing equalRowHeights() too much
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function() {
                $this.equalRowHeights();
            }, 50);
        });
        $this.data('equalRowHeights', true);
    }   
};

Here's a fiddle

I took dclawson's excellent answer and made some edits so it works in other situations, particularly with nested elements as is commen in bootstrap rows.

$.fn.resEqHeight = function(options) {
    var defaults = {
        child: false
    };
    var options = $.extend(defaults, options);

    var $el = $(this);
    if ($el.length > 0) {
        if(!$el.data('resEqHeight')) {
            $(window).bind('resize.resEqHeight', function () {
                $el.resEqHeight(options);
            });
            $el.data('resEqHeight', true);
        }
    } else {
        console.log("No items found for resEqHeight.");
    }

    if( options.child && options.child.length > 0 ){
        var elmtns = $(options.child, this);
    } else {
        var elmtns = $(this).children();
    }

    var prevTop = 0;
    var max_height = 0;
    var elements = [];
    elmtns
        .height('auto')
        .each(function() { $(this).data('resEqHeight.top', $(this).offset().top ); })
        .each(function(index) {
            var $el2 = $(this);
            var thisTop = $el2.data('resEqHeight.top');

            if (index > 0 && prevTop != thisTop) {
                $(elements).height(max_height);
                max_height = $el2.height();
                elements = [];
            }
            max_height = Math.max(max_height, $el2.height());

            prevTop = thisTop;
            elements.push(this);
        });

    $(elements).height(max_height);
};

It works with the same syntax

$('.equalheight').resEqHeight();
$('.equalheight-frame').resEqHeight({child:'.frame'});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top