Webサイトのレイアウトを調整する際に、「要素の高さを揃える」と見栄えが格段に良くなります。また最近流行りのカード型レイアウトでデザインをする際にも、要素の高さを揃えたくなるケースが出てきたりします。この手のJavaScriptやjQueryのライブラリやプラグインは数多く存在していると思いますが、そうしたものに頼らずとも意外と簡単に実装できたりします。今回は自分の手で実装する方法について書いてみます。
サンプル
JavaScriptコード
function equalBoxHeight(elm, num) {
var elm = jQuery(elm);
elm.each(function (i) {
var height;
var $this = jQuery(this);
if (i === 0 || i % num === 0) {
height = $this.height();
for (var n = i + 1; n <= i + num - 1; n++) {
if (height < elm.eq(n).height()) {
height = elm.eq(n).height();
}
}
for (var n = i; n <= i + num - 1; n++) {
elm.eq(n).css("height", height + "px");
}
}
});
}
equalBoxHeight(".p1", 3);
equalBoxHeight(".p2", 3);
サンプルのソースコードはjsdo.itで確認可能です。
実装方法
関数化する前の処理の部分から説明していきます。
上記サンプルの高さを揃える前の状態が以下の画像となります。配列の添字に合わせて、番号を0から振っています。それから高さもわかりやすくするために、それぞれ「10」、「20」、「30」としました。以下の画像を元に説明していきます。

1. 高さを揃えたい要素を取得してループさせる
今回は「p1」と値をつけたclass属性を持った要素の高さを揃えていきます。「elm」変数に、jQueryを使ってclass属性「p1」の要素を代入し、jQueryのeachメソッドでループ処理させます。
var elm = $(".p1");
elm.each(function (i) {
}
2. それぞれの行に指定するデフォルトの高さを指定する
まずheight変数を用意してデフォルトの高さを指定します。デフォルトの高さは行の一番左にある要素の高さにします。今回は1行に3つの要素があるので、添字が0か、または3で割り切れる数字のものが対象の要素となります。
if (i === 0 || i % 3 === 0) {
var height = $(this).height();
}
今回の例では、1行目が添字「0」の要素の高さ「30」、2行目が添字「3」の要素の高さ「10」がそれぞれのデフォルトの高さとなります。
3. 行ごとにループ処理させて、それぞれの高さを比較、一番大きい値の高さを取得する
デフォルトの高さ指定した変数heightを、同じ行にある他の要素の高さと比較して、大きい値のものがあればその値に置き換えていきます。
1行目には[要素0(高さ30)、要素1(高さ10)、要素2(高さ20)]の3つの要素があります。考え方としては、「要素0」の高さがデフォルトの高さとなっているので、2番目の要素「1(高さ10)」から、最後の要素「2(高さ20)」まで1つずつ高さを比較して、デフォルトの高さ「30」より大きいものがあれば、その値を変数heightに代入して置き換えていくということになります。2行目も同様です。
if (height < elm.eq(n).height()) {
height = elm.eq(n).height();
}
1行目には[0、1、2]、2行目には[3、4、5]の3つの要素があります。それぞれの行の2番目の要素「i + 1」からループ処理を始めて、最後の要素「i + 3 - 1」の時に終わらせます。それぞれ行の最初の要素の時にループ処理を実行させたいので、ステップ2の条件分岐の中に処理を書きます。
if (i === 0 || i % 3 === 0) {
var height = $(this).height();
for (var n = i + 1; n <= i + 3 - 1; n++) {
if (height < elm.eq(n).height()) {
height = elm.eq(n).height();
}
}
}
今回の例では、以下のようになります。
1行目
heightの値が「30」。2番目の要素[1]の高さは「10」⇒heightはそのまま。3番目の要素[2]の高さは「20」⇒heightはそのまま。
2行目
heightの値が「10」。2番目の要素[4]の高さは「30」⇒heightは「30」に置き換わる。3番目の要素[5]の高さは「20」⇒heightはそのまま。
つまり、最終的にheightの高さは、1行目⇒「30」、2行目⇒「30」
4. 取得した行の高さの最大値をそれぞれの要素に指定する
こちらもステップ3と同様にループ処理を使って、ステップ3で取得した高さの最大値をそれぞれの要素に指定していきます。ループ処理はそれぞれの行の最初の要素「i」から始めて、最後の要素「i + 3 - 1」の時に終わらせます。それぞれ行の最初の要素の時にループ処理を実行させたいので、ステップ2の条件分岐の中に処理を書きます。
if (i === 0 || i % 3 === 0) {
for (var n = i; n <= i + num - 1; n++) {
elm.eq(n).css("height", height + "px");
}
}
5. まとめると
1〜4をまとめると以下のようなコードになります。
// 変数elmにclass属性「p1」の要素を代入
var elm = $(".p1");
// 変数elmに対してjQueryのeachメソッドでループ処理
elm.each(function (i) {
// 添字が0か、または3で割り切れる数字のときに処理を実行
if (i === 0 || i % 3 === 0) {
// デフォルトの高さを変数heightに指定
var height = $(this).height();
// 行の2番目の要素から処理を始めて、最後の要素で終わらせる
for (var n = i + 1; n <= i + 3 - 1; n++) {
// デフォルト値より高さが大きい場合
if (height < elm.eq(n).height()) {
// heightの値を置き換える
height = elm.eq(n).height();
}
}
// 行の最初の要素から処理を始めて、最後の要素で終わらせる
for (var n = i; n <= i + 3 - 1; n++) {
// 取得した高さの最大値をそれぞれの要素に指定
elm.eq(n).css("height", height + "px");
}
}
});
6. 関数にして汎用的に使えるようにする
上記のコードを汎用的に使えるように関数にしてみます。関数の引数に「高さを揃えたい要素のclass属性値」と、「1行の中にある要素数」を指定するようにすると、以下のようなコードとなります。
function equalBoxHeight(elm, num) {
var elm = $(elm);
elm.each(function (i) {
var height;
var $this = $(this);
if (i === 0 || i % num === 0) {
height = $this.height();
for (var n = i + 1; n <= i + num - 1; n++) {
if (height < elm.eq(n).height()) {
height = elm.eq(n).height();
}
}
for (var n = i; n <= i + num - 1; n++) {
elm.eq(n).css("height", height + "px");
}
}
});
}
以下のようにして関数を実行します。
equalBoxHeight(".p1", 3);
equalBoxHeight(".p2", 3);
.forEach()メソッドを使って書くと、すっきり書くことができます。
[[".p1", 3], [".p2", 3]].forEach(function (a) {
equalBoxHeight(a[0], a[1]);
});
Underscore.jsを使って書く場合は以下のようになります。
<script src="underscore.js"></script>
<script>
_.each([[".p1", 3], [".p2", 3]], function (a) {
equalBoxHeight(a[0], a[1]);
});
</script>
コメント