DigiPress

Highly Flexible WordPress Theme

メニュー

Masonryより高機能!フィルタ、ソート、レスポンシブ対応のグリッドレイアウト「Muuri.js」

タイル状に可変グリッドレイアウトを簡単に実装できる、今や定番のjqueryプラグインといえば「Masonry」。

しかし、このMasonryには配置したアイテムを指定したタグを持つもののみ表示するフィルター機能や、目的別に並べ替えるソート機能がありません
「Masonry」プラグインのこれらの弱点を補ってくれる代替のプラグインとして有名なのが、「isotope」というjQueryプラグインがありますが、こちらは商用利用の場合はライセンス料の支払いが必要となってしまいます。

そこで今回紹介するのは、フィルター機能もソート機能も搭載した可変グリッドレイアウトを実現し、レスポンシブにも対応した、無料で商用利用も可能なJavascriptプラグイン「Muuri」(GitHubはこちら)。
MITライセンスで、IE9〜をサポートしています。

なお、Masonryは単体で利用可能で圧縮された状態のファイルサイズが 30KB なのに対して、Muuriは圧縮状態のファイルサイズが 40KB で、アニメーション用に Web-Animations.js(minified時で47KB前後)、ドラッグ用に Hammer.js(minified時で45KB前後) という外部スクリプトが場合によっては必要となります。
ただし、MasonryはjQueryが前提ですが、MuuriはjQueryは不要です。

最もシンプルな実行例

フィルターもソートもドラッグも考慮せず、すべてデフォルトのパラメータで最もシンプルなコードだけ(new Muuri(selector);)で可変グリッドレイアウトを表示した場合のデモがこちら。

See the Pen
Grid layout sample #1 by muuri.js
by digistate (@digistate)
on CodePen.

基本構成

下準備

「Muuri」は、単体のスクリプトのみでも十分機能しますが、内部アニメーションとアイテムをドラッグ可能にするには、それぞれ以下のスクリプトを先に読み込む必要があります。

内部アニメーションを行うためのスクリプト

Web-Amination.js」をロードします。

<script src="web-animations.min.js"></script>
<!-- CDN経由の場合 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.3.1/web-animations.min.js"></script>

CDN上のURLはこちら

ドラッグ操作を有効にする場合のスクリプト

Hammer.js」をロードします。

<script src="hammer.min.js"></script>
<!-- CDN経由の場合 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>

CDN上のURLはこちら

必要に応じて上記のスクリプトをロードしてから、メインの「Muuri」をロードします。

<script src="muuri.min.js"></script>

HTMLマークアップ

基本となるマークアップは以下のとおり。

<!-- コンテナ -->
<div class="grid">
  <!-- アイテム1 -->
  <div class="item">
    <div class="item-content">
      <!-- カスタムコンテンツ開始 -->
      カスタムコンテンツ
      <!-- カスタムコンテンツ終了 -->
    </div>
  </div>

  <!-- アイテム2 -->
  <div class="item">
    <div class="item-content">
      <!-- カスタムコンテンツ開始 -->
      <div class="my-custom-content">
        Yippee!
      </div>
      <!-- カスタムコンテンツ終了 -->
    </div>
  </div>
  :
</div>

まず、このマークアップでは全体を括るコンテナ要素に .grid というセレクタが付けられていて、「Muuri」には初期化の際にこのセレクタを渡すだけで可変グリッドレイアウトを構成してくれます。
.grid の中には、各アイテム(タイル)を構成する単位となる .item があり、これは配置を行う対象として必要です。
さらに、.item の内部には .item-content があり、これはアイテムの可視化のアニメーションを行うために必要となります。

実際に表示したいアイテムごとのカスタムコンテンツは、この .item-content の中に記述し、アイテム用のCSSも、この .item-content か、この内部のカスタムコンテンツに対してスタイリングするようにします。

また、グリッドレイアウトを構成するには、アイテムが最低2つは必要となります。

CSS

最低限指定が必要なCSSもたったこれだけで済みます。

/* グリッドレイアウトのコンテナ */
.grid {
  position: relative;
}

/* アイテム */
.item {
  display: block; /* 必須 */
  position: absolute; /* 必須 */
  width: 100px; /* アイテムの幅 */
  height: 100px; /* アイテムの高さ */
  margin: 5px; /* アイテム間のマージン(この2倍になる) */
  z-index: 1;
}

アイテム要素(.item)には、display:blockposition:absolute は必ず指定しておきます。
あとは、基準とするコンテナ要素の幅に何グリッド分に分割するかを決めて、グリッドの最小単位となる幅(width)と、必要に応じてアイテム間のマージンを算出してスタイリングします。

今回のサンプルでは、この記事に埋め込まれる幅を基準とするため、コンテナである .grid には width を指定し、margin でセンタリングしています。

.grid {
  position: relative;
  width:878px;
  max-width:100%;
  margin:0 auto;
}

レスポンシブ化(メディアクエリ)


「Muuri」によるグリッドレイアウトは、表示幅が狭くなっても、オーバーフローせずにアイテムがアニメーションしながら下方に並んで再配置されるようになっていますが、元のコンテナ幅を基準にしたアイテムサイズのままであるため、レイアウトが可変した際に右側に余白ができてしまいます。

コンテナ幅以下になった場合は、CSSのメディアクエリで改めてアイテムサイズをリサイズして、表示幅にフィットするようにレスポンシブに対応させてみます。

/* 877ピクセル幅以下になったら3カラム化 */
@media ( max-width : 877px ){
  .item{
    width:calc(33.33% - 11px);
    height:calc(33.33vw - 11px);
  }
}

/* 640ピクセル幅以下になったら2カラム化 */
@media ( max-width : 640px ){
  .item{
    width:calc(50% - 10px);
    height:calc(50vw - 10px);
  }
}

Javascript

HTMLのマークアップと、先述の最低限のCSSだけ整えば、以下のJavascriptの1行だけで可変グリッドレイアウトが表示されます。

var grid = new Muuri('.grid');

アイテムのドラッグを有効にする

グリッドレイアウトの各アイテムをドラッグして入れ替え可能にするには、まずは先述の hammer.js を読み込むようにしておき、「Muuri」の初期化の際にドラッグを有効にするようオプションパラメータをセットしておきます。

var grid = new Muuri('.grid', {
  dragEnabled: true
});

オプションとして、たった dragEnabled: true を指定するのみでOKです。
その他、指定可能なドラッグ機能に関する細かなオプションについてはこちら

また、ドラッグ中は他のアイテムよりも前面にさせる必要があるため、ドラック中に自動的に対象アイテムに挿入されるセレクタ(.muuri-item-dragging)に対して、z-indexを指定しておきます。

.item.muuri-item-dragging {
  z-index: 3;
}

ドラッグ操作を有効にした場合のデモ

See the Pen
Grid layout sample #2 by muuri.js (Enable dragging)
by digistate (@digistate)
on CodePen.

フィルター/ソート機能を実装する

「Muuri」で表示するグリッドレイアウトに、フィルター機能を反映するには、まずはアイテムごとにグルーピングするための「タグ付け」をしておきます。
そうすることで、「Muuri」は同じ「タグ」を持つアイテムのみをフィルタリングして表示してくれます。

フィルタリングのための準備

「タグ付け」の方法は、2種類あります。

classにタグ用のセレクタを含める

.item 要素の class にタグとなる任意のセレクタ(文字列)を含めて、これをフィルタリングのキーとする場合は、以下のコードで「Muuri」で生成したグリッドレイアウトのオブジェクトにフィルターを実行させることができます。

アイテムのマークアップ

<div class="item foo">
  <div class="item-content">
    Item 1
  </div>
</div>

Javascript

var grid = new Muuri('.grid');
// foo というセレクタを持つアイテムのみを表示
grid.filter('.foo');

data属性によるタグ付け

classの場合は、スペースを含む場合やclassの値に含められないものをタグにする必要がある場合は不向きです。
このような場合は、.item 要素に任意の data属性を設けてタグ付けを行い、「Muuri」のfilterメソッドにそのdata属性の値を渡すことでフィルタリングが可能になります。

var grid = new Muuri('.grid');
// data-color属性の値に「red」を持つアイテムのみを表示
grid.filter(function(item){
  var element = item.getElement();
  return element.getAttribute('data-color') === 'red';
});

これを応用して、フォーム要素にフィルタリング対象となるvalueを持たせて、例えばselect要素のイベントリスナーを登録して、選択されたoption要素のvalue値と、アイテムのdata属性の値が一致する場合のみtrueを返してフィルタリングさせることができるようになります。

フィルター(検索含む)/ソート機能を実装した場合のデモ

以下のデモでは、フォーム(select)要素に予めフィルタリングのための「タグ」がセットされた絞り込みに加え、検索ワードのフォーム(input)要素がありますが、それぞれにイベントリスナーがあり、処理自体はどちらも同じ grid.filter メソッドでフィルタリングしているだけです。
ただし、select要素の場合は、data-color 属性、検索ワード(input) の場合は、data-title という属性の値を比較対象にしています。

See the Pen
Grid layout sample #3 by muuri.js (Filter/Sort)
by digistate (@digistate)
on CodePen.


その他、オプションパラメータグリッドメソッドアイテムメソッドイベントなど、かなり豊富な種類があるので、細かな要件や非常に凝った可変グリッドレイアウトコンテンツにもほぼ対応できそうです。

Share / Subscribe
Facebook Likes
Tweets
Hatena Bookmarks
Pinterest
Pocket
Feedly
Send to LINE