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>

asked Aug 23, 2016 at 6:38
\$\endgroup\$
4
  • 3
    \$\begingroup\$ @Tushar Code Review does NOT want an MCVE: meta.codereview.stackexchange.com/a/6256/10582 \$\endgroup\$ Commented Aug 23, 2016 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\$ Commented Aug 23, 2016 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\$ Commented Aug 23, 2016 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\$ Commented Aug 23, 2016 at 12:38

1 Answer 1

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.
answered Aug 23, 2016 at 8:54
\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your answer, but could just explain a bit about why this method is better? \$\endgroup\$ Commented Aug 23, 2016 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\$ Commented Aug 23, 2016 at 22:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.