メーソンリーグリッドレイアウトシステム
目的
メーソンリーグリッドレイアウトシステムは、写真ポートフォリオ、ユーザー生成コンテンツフィード、混合メディアカード、エディトリアルビジュアルディスカバリーボードなど、高さが不均一なコンテンツカードを表示するための、標準化されたレスポンシブデザインフレームワークを提供します。標準のCSSグリッドレイアウトでは行の高さが揃えられるため、アイテムのアスペクト比やテキストの長さが異なる場合に不自然な垂直方向の空白が生じます。
効果的なメーソンリーグリッドを設計するには、アイテムを動的に並列な垂直カラムに詰め込むという空間的な課題を解決し、メディアアセットの読み込みに伴う累積レイアウトシフト(CLS)を防止し、モバイルでのカラム数の段階的減少を適切に処理し、さらに重要なこととして、視覚的なレイアウトが論理的なDOM読み取り順序やキーボードフォーカスナビゲーションの順序(WCAG 2.1 SC 1.3.2およびSC 2.1.1)を壊さないようにする必要があります。
ユースケース
- 写真・ビジュアルメディアポートフォリオ: さまざまなネイティブアスペクト比(ポートレート、ランドスケープ、スクエア、パノラマ)の画像ギャラリーを、タイトで隙間のないグリッドに表示します。
- ソーシャル・UGCアクティビティフィード: 短いテキスト更新、長文記事、埋め込み画像、動画ティーザーを含む混合ソーシャルカードを整理します。
- EコマースUGC・レビューウォール: カスタマーレビュー写真、タグ付けされたInstagram投稿、商品ハイライトスニペットを動的なディスカバリーショーケースに表示します。
- エディトリアルディスカバリー・ピンボード: ムードボード、ブックマークマネージャー、インスピレーションフィードを構築します。カードには多様なコンテンツ要素と可変の垂直フットプリントが含まれます。
使用すべきでないケース
- 均一なアスペクト比のグリッド: すべてのアイテムが同一のアスペクト比(例:標準の16:9動画カードや1:1商品カタログ)を共有する場合は、
responsive-grid-systemまたはcard-ui-systemを使用します。 - 構造化された2D非対称ハイライト: 明示的な2D矩形スパンルール(例:2x2のメインフィーチャーと1x1の統計ブロック)を持つキュレーションされたヒーローセクションには、
bento-grid-layout-systemを使用します。 - 厳密な表形式・整列データ: ユーザーが水平方向の行をまたいで値を比較する必要がある場合(例:価格表や財務指標)は、
data-table-ui-systemまたはcomparison-matrix-systemを使用します。 - 順次ストーリーテリング・記事: 読み取り順序が単一の垂直フローに厳密に従う必要がある線形ナラティブには、
article-layout-systemまたはsection-composition-systemを使用します。
入力
- コンテンツインベントリとアスペクト比: メディアおよびテキストコンテンツの種類(画像、動画、テキストスニペット、アクションカード)と、そのアスペクト比の範囲(3:4ポートレートから16:9ランドスケープまで)。
- カラム構成要件: 画面サイズごとのターゲットカラム数(例:ワイドスクリーンデスクトップでは4カラム、デスクトップでは3カラム、タブレットでは2カラム、モバイルでは1カラム)。
- インタラクティブ性とフォーカス要件: カード内のインタラクティブ要素(ボタン、ライトボックス、インライントグル、リンク)で、キーボードアクセシビリティが必要なもの。
- スペーシャルおよびテーマトークン: 流動的なカラムガターと行間隔(
gap: clamp(12px, 2vw, 24px))、カードの背景塗りつぶし、ボーダー半径、フォーカスリングトークン(fluid-spacing-systemおよびfocus-indicator-design-systemから)。
出力
- メーソンリーレイアウトアーキテクチャ仕様: 純粋なCSSマルチカラムフロー、CSS Grid行スパン(
grid-auto-rows)、JavaScript最短カラムパッキングの間での戦略的な選択と技術的な設計図。 - レスポンシブカラムスケーリングマトリックス: スムーズなカラム数遷移とギャップスケーリングのためのブレークポイント定義。
- DOM読み取り順序とキーボードフォーカスマップ: キーボードナビゲーション(
Tab/Shift+Tab)が自然な視覚的な読み取り順序に従い、カオスなカラムジャンプが発生しないアーキテクチャ。 - レイアウト安定性とアスペクト比保持ルール: 画像およびメディア読み込み中の累積レイアウトシフト(CLS)を防止するCSSアーキテクチャ。
ワークフロー
1. アーキテクチャ戦略の選択
インタラクティブ性と読み取り順序の要件に基づいて、適切なレイアウト手法を選択します。
- オプションA: 純粋なCSSマルチカラムレイアウト(
column-count)- 最適: 静的ギャラリー、画像主体のフィード、またはフローがカラム1を垂直に下ってからカラム2に進む順序で問題ない非インタラクティブカード。
- 実装:
column-count: 4; column-gap: var(--space-m);。子カードにbreak-inside: avoid; margin-bottom: var(--space-m);を設定します。 - トレードオフ: 垂直方向のソース順序(カラム内で上から下)は、カードにインタラクティブコントロールが含まれる場合、キーボードユーザーを混乱させる可能性があります。
- オプションB: 行スパン付きCSS Grid(
grid-auto-rowsとgrid-row: span X)- 最適: カードの高さを固定の行トラック単位(例:
10pxベーストラック)に量子化できる半静的なグリッド。 - 実装:
display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); grid-auto-rows: 10px; gap: 16px;。JavaScriptでコンテンツの高さを計算し、grid-row: span Math.ceil(height / trackHeight)を適用します。 - トレードオフ: ネイティブの水平方向のDOM順序が維持されますが、軽微なJS高さ計算またはコンテナクエリが必要です。
- 最適: カードの高さを固定の行トラック単位(例:
- オプションC: JavaScript最短カラムコンテナ分配
- 最適: 左から右への読み取り順序が最も重要であり、カードにリンク、ボタン、フォームコントロールが含まれる、高度にインタラクティブな混合メディアフィード。
- 実装: $N$個のフレックスカラムコンテナを作成します(
display: flex; flex-direction: column; gap: var(--space-m);)。現在のレンダリング高さが最も短いカラムに、新しいカードを追加入力します。 - トレードオフ: クライアント側のDOMコンテナ管理が必要ですが、完全な左から右のDOMフォーカスフローと視覚的な垂直ギャップゼロを保証します。
2. 空間リズムとカラムガターの定義
すべてのカラムとカード内部パディングで一貫したスペーシングトークンを確立します。
- カラムガター: 流動的なギャップスペーシングを使用します(例:
gap: clamp(16px, 2.5vw, 28px))。積み重ねられたカード間の垂直方向の間隔が水平方向のカラム間隔と等しくなるように、均一な空間密度を維持します。 - カードパディングと内部配置: 流動的なトークン(
padding: var(--space-m))を使用してカード内部のパディングを標準化します。メディアのみのカード(例:ライトボックストリガー)では、画像が端から端まで表示されるようにします(padding: 0; overflow: hidden;)。 - コーナー半径の同期: 外側のカードコンテナに一貫した border-radius を適用します(例:
12pxから16px)。内側の要素(例:上部の画像)が同心のコーナー半径を継承するようにします(border-top-left-radius: calc(var(--card-radius) - 1px))。
3. レイアウトシフト(CLS)と画像歪みの防止
メーソンリーグリッドは、画像読み込み中の累積レイアウトシフト(CLS)の影響を非常に受けやすくなっています。
- アスペクト比ボックス: 画像コンテナに明示的に
aspect-ratioを宣言します(aspect-ratio: 4 / 5; object-fit: cover; width: 100%; display: block;)。または、メディアが解決される前にインラインパディング比率を計算します。 - スケルトンプレースホルダー: リモートアセットの読み込み中に、期待されるカードのアスペクト比に一致するスタイル付きのスケルトン背景パルス(
background: var(--surface-subtle); animation: pulse 1.5s infinite;)をレンダリングします。 - 画像読み込みリスナー: JSの高さ計算を使用する場合、
ResizeObserverまたは画像のloadイベントリスナーをバインドして、画像のレンダリングが完了した後にカラムの高さ割り当てを再計算します。
4. DOM読み取り順序とフォーカス管理の調整
WCAG 1.3.2(意味のあるシーケンス)および2.1.1(キーボード)への準拠を確実にします。
- ビジュアルとDOMの不一致の回避: CSSカラムを使用して視覚的なレイアウトがカラムを垂直に流れる場合、キーボードフォーカスインジケータが明確で論理的であることを確認します。カードにインタラクティブコントロールが含まれる場合は、JavaScript最短カラム分配またはCSS Grid行スパンを優先して、自然な左から右、上から下のタブ順序(
Tabキー順序)を維持します。 - フォーカスインジケータの可視性: 高コントラストでクリップされないフォーカスインジケータを標準化します(
outline: 3px solid var(--focus-ring-color); outline-offset: 3px;)。クリップ境界内に十分なフォーカスインジケータパディングを追加せずに、カードにoverflow: hiddenを設定しないでください。 - ライトボックス/モーダルのキーボードショートカット: メーソンリーカードをクリックしてモーダルオーバーレイまたはライトボックスを開く場合、キーボードフォーカスをオーバーレイ内にトラップし(
focus-trap)、閉じたとき(Escapeキー)にフォーカスを元のカードトリガーに戻します。
5. レスポンシブカラムスケーリングの実装
コンテンツのバランスを崩さずにカラム数を段階的にスケーリングするブレークポイントを設計します。
- ワイドスクリーンデスクトップ(≥ 1440px): 4カラム(
column-count: 4または4つのフレックスカラムトラック)。 - 標準デスクトップ(1024px – 1439px): 3カラム(
column-count: 3または3つのフレックスカラムトラック)。 - タブレット/小画面(640px – 1023px): 2カラム(
column-count: 2または2つのフレックスカラムトラック)。 - モバイル(< 640px): 1カラム(
column-count: 1または単一の垂直スタック)。すべてのアイテムが標準の垂直スペーシングで自然に積み重なります。
決定ルール
アーキテクチャ選択マトリックス
| コンテンツとインタラクションのタイプ | 推奨アーキテクチャ戦略 | 理由 |
|---|---|---|
| 純粋な画像ギャラリー(ライトボックストリガー) | CSSマルチカラム(column-count) | JSフットプリントゼロ、ネイティブブラウザマルチカラムパフォーマンス、クリーンな垂直画像メーソンリー。 |
| インタラクティブカード(ボタン、入力、リンク) | JS最短カラムフレックス分配 | 厳密な左から右のDOMタブ順序を保持し、スクリーンリーダーとキーボードフォーカスのジャンプを防止。 |
| 動的読み込みフィード(無限スクロール) | CSS Grid行スパンまたはJSカラム分配 | ページ全体のレイアウトをリフローせずに、新しいカードを最短カラムにスムーズに追加可能。 |
| テキスト主体のエディトリアルピンボード | CSS Grid行スパン(grid-auto-rows: 10px) | 水平方向の読み取り順序を維持しながら、可変のテキスト長に正確に対応。 |
制約
- アクセシビリティ(WCAG 2.1 AA準拠):
- SC 1.3.2 意味のあるシーケンス: インタラクティブカードの視覚的な配置は、キーボードタブナビゲーション順序(
tabindex="0"フォーカスフロー)と論理的に一致している必要があります。 - SC 1.4.3 コントラスト(最低限): カード表面または画像オーバーレイ上にレンダリングされるテキストは、最低 4.5:1 のコントラスト比を満たす必要があります。画像上に直接配置されるテキストには、暗いスクリムオーバーレイ(
background: linear-gradient(to top, rgba(0,0,0,0.8), transparent))を使用する必要があります。 - SC 2.1.1 キーボード: すべてのインタラクティブカード要素(ボタン、ブックマークトリガー、外部リンクなど)は、
SpaceキーとEnterキーで完全に操作可能である必要があります。 - SC 2.4.7 フォーカス可視: インタラクティブカードとトリガーは、親カードの
overflow: hiddenプロパティによってクリップされない、明確なフォーカスリングを表示する必要があります。 - SC 2.5.8 ターゲットサイズ: メーソンリーカード内のすべてのタッチターゲットは、最小インタラクティブ領域 24x24px(タッチ/モバイルビューポートでは最低 44x44px)を維持する必要があります。
- SC 1.3.2 意味のあるシーケンス: インタラクティブカードの視覚的な配置は、キーボードタブナビゲーション順序(
- レイアウトシフトパフォーマンス: メーソンリーカード内の画像には、CLSが 0.1 未満に維持されることを保証するため、明示的に定義された内在アスペクト比または寸法予約が必要です。
共通の障害パターン
- キーボードタブの混乱: インタラクティブカードにCSS
column-countを使用すると、キーボードのTabキーが最初のカラム全体を垂直に移動してから(アイテム1からアイテム10へ)、2列目の先頭にジャンプして戻る原因となります。 - 累積レイアウトシフト(CLS)の混乱: アスペクト比スタイルやローディングスケルトンなしで画像を挿入すると、画像が読み込まれるたびにメーソンリーカラムがリフローして繰り返しジャンプします。
- クリップされたフォーカスリング: 丸みを帯びた画像コーナーを強制するためにメーソンリーカードに
overflow: hiddenを設定すると、インタラクティブな内部要素の標準のアウトラインフォーカスリングが切り取られます。 - モバイルでのカラム高さ制約の欠如: モバイルデバイスでメーソンリーグリッドを1カラムに折りたたむことができず、その結果、極端に狭く押しつぶされたマルチカラムカードとなり、テキストの折り返しが読みにくくなります。
- 不均一なカラム集計: 動的フィードで新しいアイテムをカラムの高さを確認せずにカラム間で順次追加(1、2、3、1、2、3)すると、短いカラムの下部に巨大な垂直方向の空白スペースが生じます。
検証基準
- アーキテクチャの整合性: 選択された戦略(CSSカラム vs. CSS Grid行スパン vs. JS最短カラム)がカードのインタラクティブ要件と一致している。
- 意図しない垂直ギャップゼロ: カードが水平方向の行揃えによる空白ギャップなしで密に詰め込まれている。
- キーボードタブナビゲーション: インタラクティブカードが論理的な視覚的タブ順序(左から右、上から下)に従っている。
- レイアウトシフト防止: アスペクト比またはスケルトンコンテナが、リモートメディアの読み込み中にCLS(<0.1)を防止している。
- レスポンシブブレークポイント適応: グリッドがワイドスクリーンの4カラムからモバイル(<640px)の1つの垂直カラムまでスムーズにスケーリングされている。
- WCAG AA準拠: すべてのテキストが≥4.5:1のコントラストを満たし、タッチターゲットが≥24x24px(モバイルでは≥44x44px)であり、フォーカスリングがクリップされず明確に表示されている。