jQuery
bootstrap
masonry
bootstrap4
gridlayout

Bootstrap4のCardsとMasonry.jsの相性が最強だった件

概要

テニスプレイヤーがLaravelでWebサービス作ってみたの個別記事です。

Masonry.jsとは画像などの矩形オブジェクトをきれいに整列させてくれるjQueryプラグインです。
CardsはBootstrap4から導入された新しいコンポーネントです。矩形の範囲に文字列や画像などを挿入して並べることができます。以前のバージョンではpanelという名前でしたが、グリッドレイアウトでの使い勝手が良くなってCardsという名前で再登場しました。
この二つを組み合わせると、伝えたい情報をパネル状にして、簡単に整列させることができます。しかもどんな大きさの画面でも見やすいレスポンシブデザインになります。

表形式で羅列するのもいいんですが、味気ないので情報の伝え方を少し工夫したいと思っていました。

動作サンプル

https://teniguru.online/

この技術を使ってアプリを作ってみました。画面の大きさを変えるとCardsがうねうね動いて、見ているだけで(自分は)楽しいです。

コード

HTML

必要なパッケージを読み込みます。

<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<!-- Bootstrap4 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<!-- Masonry -->
<script src="https://unpkg.com/masonry-layout@4.2.1/dist/masonry.pkgd.min.js"></script>

続いてbodyの内容を書きます。

<div class="container">
  <!-- .grid-indexでCards全体をネストする -->
  <div class="grid-index">
    <!-- ウインドウサイズごとにグリッドサイズを定義。スマホだと横に1つ、タブレットだと2つ、PCだと3つ並べる -->
    <div class="grid-sizer col-12 col-sm-6 col-lg-4"></div>

    <!-- Card1 -->
    <div class="grid-item col-12 col-sm-6 col-lg-4">
      <div class="card">
        <div class="card-block">
          <div class="card-title">
            <h5>
              Card1のタイトル
            </h5>
          </div>
          <div class="card-text">
            Card1の内容
          </div>
        </div>
      </div>
    </div>
    <!-- Card1ここまで -->

    <!-- Card2 -->
    <div class="grid-item col-12 col-sm-6 col-lg-4">
      <div class="card">
        <div class="card-block">
          <div class="card-title">
            <h5>
              Card2のタイトル
            </h5>
          </div>
          <div class="card-text">
            Card2の内容
          </div>
        </div>
      </div>
    </div>
    <!-- Card2ここまで -->

    <!-- Card3 -->
    <div class="grid-item col-12 col-sm-6 col-lg-4">
      <div class="card">
        <div class="card-block">
          <div class="card-title">
            <h5>
              Card3のタイトル
            </h5>
          </div>
          <div class="card-text">
            Card3の内容
          </div>
        </div>
      </div>
    </div>
    <!-- Card3ここまで -->

  </div> <!-- .grid-index -->
</div> <!-- .container -->

ここまででもグリッドレイアウトになり、レスポンシブもしてくれます。
しかし同じ行のCardsの高さがまちまちだと、次の行のCardが詰まってくれないので隙間が空いてしまい、見た目が良くないです。
card (1).png

Masonryを使うことで解決します。

jQuery

$(function(){
    $('.grid-index').masonry({
        itemSelector: '.grid-item',
        columnWidth: '.grid-sizer',
        percentPosition: true
    });
});

基本的にこれだけです。隙間が詰まって整然と並んでくれます。ウインドウサイズを変えるとうねうねするようになります。

時々Cardsが全部重なったまま並んでくれないことがあります。
その場合はコンポーネントをすべて読み込んでからMasonryを発火させるために動作遅延の処理を入れてあげます。

$(function(){
   //読み込み完了後0.2秒待ってからmasonryする
    var cnt = 0;
    var waiting = setInterval(function(){
        if(cnt == 1) {

            $('.grid-index').masonry({
                itemSelector: '.grid-item',
                columnWidth: '.grid-sizer',
                percentPosition: true
            });

            clearInterval(waiting);
        }
        cnt++;
        }, 200);
});