4
\$\begingroup\$

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);
        });

        // 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);
.box {
    background: #efefef;
    float: left;
    margin: 0 16px 16px 0;
    width: 200px;
}
.box-title {
    background: #ccc;
    margin-top: 0;
    padding: 16px;
}
.box-content {
    padding: 16px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
    <head>
        
    </head>
    <body>
        <div class="box"><h2 class="box-title" data-equalize='title'>This is a short title</h2><div class="box-content" data-equalize='content'><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p></div></div>
        <div class="box"><h2 class="box-title" data-equalize='title'>This is a long title that would possibly go over a couple of lines</h2><div class="box-content" data-equalize='content'><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries.</p></div></div>
    </body>
</html>

\$\endgroup\$
  • 3
    \$\begingroup\$ @Tushar Code Review does NOT want an MCVE: meta.codereview.stackexchange.com/a/6256/10582 \$\endgroup\$ – BCdotWEB Aug 23 '16 at 7:59
  • 2
    \$\begingroup\$ You should use jQuery when it is relevant, and don't when it is not. There is no hard and fast rule for "how much" jQuery you should use. \$\endgroup\$ – Dan Pantry Aug 23 '16 at 9:17
  • \$\begingroup\$ In the majority of cases where two elements have to be "equalized", they are two columns, in which case you should actually do it with css and not with jquery (or javascript or magic). \$\endgroup\$ – Sumurai8 Aug 23 '16 at 9:23
  • 1
    \$\begingroup\$ If you can add live example, this might be done using CSS flex layout only with no need of JS code. \$\endgroup\$ – Tushar Aug 23 '16 at 12:38
2
\$\begingroup\$

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 = $('<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.
\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer, but could just explain a bit about why this method is better? \$\endgroup\$ – ngearing Aug 23 '16 at 22:26
  • \$\begingroup\$ Well, I'm not sure what needs explanation. I can state the obvious: 1. doing more work with less effort (be it code or, more specifically, iterations therein) is more efficient by definition 2. not touching DOM is better because DOM is slow. \$\endgroup\$ – wOxxOm Aug 23 '16 at 22:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.