ビューポートの幅に応じてn要素毎に高さ揃えをするプラグインの改良

公開

n要素毎に高さ揃えができる自作プラグイン(といっても、前職在籍時の2010年頃にライブラリのコードリーディングをして勉強したことがあるので、よく似ているのですが)を使っていて、オプションで{ groupBy: 3 }のように要素数を指定をしているのですが、レスポンシブWebデザインのサイトを設計・実装する際、画面幅によってnの値を変えたい場合が時々出てきます。

以前MJLで高さ揃えをする際、ビューポートの幅に応じて何個ごとに高さ揃えをするか変えることを検討してみたに書いたように.matchMedia()も使ったりしたのですが、どうも手間がかかります。同じことを繰り返すならもっと楽をしたいと思案したところ、groupByの値に画面幅とグルーピングする要素数を書けば良いかと思いつき、実装したところ上手くいきました。

コードの改善ポイント

オプションは次のように配列で指定します。

{
    groupBy: [
        {
            maxWidth: 479,
            groupBy: 0    // 高さ揃えをキャンセル
        },
        {
            maxWidth: 767,
            groupBy: 2
        },
        {
            maxWidth: 99999,
            groupBy: 3
        },
    ]
}

プラグインでは、まずgroupByの値がオブジェクト(JavaScriptなので、配列もtypeofの結果はオブジェクト)の場合、ブレークポイントを収集しておきます。

defineGroupByVal: function () {
    var groupBySetting = this.options.groupBy,
        breakPoints = [];

    groupBySetting.forEach(function (setting) {
        breakPoints.push(setting.maxWidth);
    });

    breakPoints.sort(
        function compareNumbers(a, b) {
            return a - b;
        }
    );
    this.breakPoints = breakPoints;
},

そして、load・resizeイベントが発火して高さ揃えをする際、ブレークポイントが格納されている場合は画面サイズをチェックして、設定にマッチするgroupByの値を抽出するようにしました。

doEqualize: function () {
    var height = [],
        nElem = this.target.length,
        i = 0,
        matchFlag = false,
        groupBy;

    // 省略

    // 高さ揃えのグループ単位を取得
    if (this.breakPoints) {
        this.breakPoints.forEach(mylib.util.proxy(this, function (breakPoint) {
            if (!matchFlag && window.innerWidth < breakPoint) {
                this.options.groupBy.filter(function (item) {
                    if (item.maxWidth === breakPoint) {
                        groupBy = item.groupBy;
                    }
                });

                matchFlag = true;
            }
        }));
    } else {
        groupBy = this.options.groupBy;
    }

    // 揃える高さを算出
    if (groupBy === 0) {
        // 高さ揃えをキャンセル
        height = [];
    } else {
        height = this._getArrangeHeight(height, nElem, groupBy);
    }

    // 要素に高さを設定
    this._setHeight(height, nElem);
},

テストで作成したファイルのレンダリング結果は次のようになりました。

  • ビューポートが680px以上の場合
    ビューポートが680px以上の場合の動作結果:3絡む表示隣、3要素毎に高さ揃えが行われている
  • ビューポートが480px〜679pxの場合
    ビューポートが480px〜679pxの場合の動作結果:2カラム表示となり、2要素毎に高さ揃えが行われている
  • ビューポートが479px以下の場合
    ビューポートが479px以下の場合の動作結果:1カラム表示隣高さ揃えは行われていない。

揃える要素数はプラグイン内で算出しても良いかもしれませんが、予め分かっているのでそこまでしなくてもよいかなと考えました。