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>
1 Answer 1
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.
-
\$\begingroup\$ Thanks for your answer, but could just explain a bit about why this method is better? \$\endgroup\$ngearing– ngearing2016年08月23日 22:26:49 +00:00Commented 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\$woxxom– woxxom2016年08月23日 22:33:42 +00:00Commented Aug 23, 2016 at 22:33
flex
layout only with no need of JS code. \$\endgroup\$