HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Javascript equalise heights of groups of elements

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
heightsgroupselementsjavascriptequalise

Problem

This is a small function I have written to equalise the height of groups of elements. Useful for when titles or content will end up being odd length and throw out the visual flow.

To use it you just add the data-equalize attr to two or more element you would like equalised. Can have multiple groups working on one page.

Would there a more optimal way to do this?

Should I be using less or more jQuery?

(function($) {
    'use strict';

    function equalHeights() {
        var i;
        var groups = [];
        $('[data-equalize]').each(function() {
            var group = $(this).data('equalize');

            // Check if this group already exists
            // If not add this group to the array
            if($.inArray(group,groups) == -1)
                groups.push(group);
        });

        // Loop through the groups and get max height
        for(i=0; groups.length>i; i++) {
            var elementGroup = $('[data-equalize='+groups[i]+']');
            var maxHeight = Math.max.apply(null, elementGroup.map(function () 
                {
                    return $(this).height();
                }
            ));

            // Set height for the group elements
            elementGroup.css('min-height', maxHeight);
        }
    }
    $(document).ready(equalHeights);

    // Heights may change when text wraps another line.
    //$(window).resize(equalHeights);
    // Use throttling instead
    var doit;
    window.onresize = function(){
        clearTimeout(doit);
        doit = setTimeout(equalHeights, 100);
    };

})(jQuery);


Update

A live example


`(function($) {
'use strict';

function equalHeights() {
var i;
var groups = [];
$('[data-equalize]').each(function() {
var group = $(this).data('equalize');

// Check if this group already exists
// If not add this group to the array
if($.inArray(group,groups) == -1)
groups.push(group);
})

Solution

Calculate maxHeight in one pass with enumeration and keep it in a dictionary for fast lookup:

function equalHeights() {
    var maxHeight = {};

    $('[data-equalize]').each(function() {
        var group = $(this).data('equalize');
        maxHeight[group] = Math.max(maxHeight[group] || 0, $(this).height());
    });

    $('[data-equalize]').each(function() {
        $(this).css('min-height', maxHeight[$(this).data('equalize')]);
    });
}


Alternatively, use CSS stylesheets in order not to modify slow DOM.

function equalHeights() {
    var maxHeight = {};

    $('[data-equalize]').each(function() {
        var $this = $(this);
        var group = $this.data('equalize');
        maxHeight[group] = Math.max(maxHeight[group] || 0, $this.height());
    });

    $style.text(
        Object.keys(maxHeight).map(function(group) {
            return '[data-equalize="'+ group +'"] {min-height:' + maxHeight[group] + 'px}';
        }).join('\n')
    );
}

var $style;

$(function() {
    $style = $('').appendTo('head').attr('id', 'equalizer-style');
    equalHeights();
});


Notes:

  • $(document).ready(fn) can be, and was, shortened to $(fn)



  • An additional microoptimization to cache $(this) was used in the second code snippet, pointless until proven otherwise in devtools Javascript profiler or via time measurement inside the code.

Code Snippets

function equalHeights() {
    var maxHeight = {};

    $('[data-equalize]').each(function() {
        var group = $(this).data('equalize');
        maxHeight[group] = Math.max(maxHeight[group] || 0, $(this).height());
    });

    $('[data-equalize]').each(function() {
        $(this).css('min-height', maxHeight[$(this).data('equalize')]);
    });
}
function equalHeights() {
    var maxHeight = {};

    $('[data-equalize]').each(function() {
        var $this = $(this);
        var group = $this.data('equalize');
        maxHeight[group] = Math.max(maxHeight[group] || 0, $this.height());
    });

    $style.text(
        Object.keys(maxHeight).map(function(group) {
            return '[data-equalize="'+ group +'"] {min-height:' + maxHeight[group] + 'px}';
        }).join('\n')
    );
}

var $style;

$(function() {
    $style = $('<style>').appendTo('head').attr('id', 'equalizer-style');
    equalHeights();
});

Context

StackExchange Code Review Q#139413, answer score: 2

Revisions (0)

No revisions yet.