Webでよく見る、Pinterestのように高さの異なるカードをきれいに並べたグリッドレイアウト。
見た目はシンプルですが、実装しようとすると「高さバラバラなのに、どうしてこんなに整ってるの?」と迷うことも多いデザインのひとつです。
【このデザイン、どうコーディングする?】シリーズ第2回では、そんな不揃いなカードを整列させるスマートな方法を取り上げます。
CSS Gridのgrid-auto-flow: dense
、マルチカラムレイアウト(column-count
)、そして比較対象としてJavaScriptを使った方法も軽く触れつつ、実務に向いた「手間なく、でも見た目はキレイ」なレイアウトを目指します。
実装イメージ&HTML構造
今回実装するのは、高さの異なるカードが整然と並ぶPinterest風のグリッドレイアウトです。
画像やテキストなど、要素ごとに高さが違っても、崩れずに視認性の高いレイアウトを維持します。
スマホでは1列で縦積み、PCでは2〜4列で横方向に展開する、レスポンシブ対応の構成です。
完成イメージ(例)
以下のようなイメージを想定しています:
┌─────┬─────┬─────┐
│ img │
img │
img │
│
txt
│
txt
│
txt
│
│
│
txt
│
│
│
img
│ │
img
│
│
txt
│ │
txt
│
└─────┴─────┴─────┘
カードごとに高さが異なるのに、列が整って見えるのがポイントです。
HTML構造(共通)
どの手法でも、基本的には同じようなHTML構造で対応できます。
以下は最もシンプルな例です。
<div class="grid">
<div class="item">
<img src="image1.jpg" alt="画像1">
<p>テキスト内容1</p>
</div>
<div class="item">
<img src="image2.jpg" alt="画像2">
<p>テキスト内容2。やや長めの説明文が入る。</p>
</div>
<div class="item">
<img src="image3.jpg" alt="画像3">
<p>短め</p>
</div>
<!-- 以下、続く -->
</div>
ポイント
.grid
:グリッド全体のラッパー.item
:1つのカード単位(画像+テキスト)
コンテンツの長さ・画像サイズは統一されていない前提で構いません。
要素の高さがバラバラであることが、今回のキモです。
CSS実装パターン比較
高さの異なる要素をPinterest風にきれいに並べる方法はいくつかあります。
ここでは、代表的な以下3つの手法を比較しながら紹介します。
方法1:CSS Grid + grid-auto-flow: dense
もっとも柔軟で、制御もしやすい方法です。
空きスペースに自動で要素を詰めてくれるのが最大の特徴。
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-flow: dense;
gap: 1rem;
}
ポイント
auto-fill
:画面幅に応じて列数が自動調整grid-auto-flow: dense
:空いているスペースを優先して埋めるgap
:要素間の余白
メリット:
- レスポンシブ対応がしやすい
- 順序の制御が効く
- スタイルの自由度が高い
注意点:
「密詰め」によってDOM順と表示順がずれる可能性あり(アクセシビリティに注意)
方法2:マルチカラムレイアウト(column-count
)
CSSだけで超シンプルに実現できる手法。ブログ風レイアウトにもよく使われます。
.grid {
column-count: 3;
column-gap: 1rem;
}
.item {
break-inside: avoid;
margin-bottom: 1rem;
}
ポイント
column-count
:列数を指定break-inside: avoid
:要素が途中で分割されるのを防止
メリット:
- 実装が非常にシンプル
- 柔軟に高さが違う要素を流し込める
注意点:
- カラム内にどのアイテムが入るかはCSS任せ(順序の制御ができない)
- フォーカス移動などが視覚順と論理順でズレる
方法3:JavaScriptでの高さ揃え(比較用)
以前よく使われていた方法。一度全アイテムの高さを取得し、手動で再配置します。
const items = document.querySelectorAll('.item');
let heights = Array.from(items).map(el => el.offsetHeight);
// ... 高さを比較して同じ列になるように位置調整(実装は結構大変)
メリット:
- 古いブラウザでも対応可能(ただし今はほぼ不要)
注意点:
- JSによるレイアウト再計算はパフォーマンスに悪影響
- ウィンドウリサイズ時の再処理が必要
- コード量が多くなり、保守性が低い
まとめ:どれを使うべき?
方法 | 特徴 | 向いているケース |
---|---|---|
grid-auto-flow: dense | 表示順の柔軟性あり・制御しやすい | 高度なUIや再利用性を重視する場合 |
column-count | 実装が速くて簡単 | 小規模な一覧や簡易的なレイアウトに |
JavaScript | 高度な制御が可能(でも非推奨) | 特殊な要件がある or レガシー対応時のみ |
実装Tipsと注意点
どの方法を使うにせよ、「うまくいかない」「想定と違う表示になる」といったケースに遭遇することがあります。
ここでは、現場で遭遇しやすい注意点と、その回避・調整方法を紹介します。
grid-auto-flow: dense
の再配置に関する注意点
このプロパティは**「空いたスペースを埋める」動作を行うため、意図しない並び順になることがあります**。
たとえば、HTMLの3番目の要素が最初に表示されるようなケースです。
.grid {
grid-auto-flow: dense;
}
- 読み上げ順やタブキーによるフォーカス順は、HTMLの順序に従うため、
視覚順と論理順がズレる可能性があることを意識する必要があります。
対策例:
aria-flowto
などで補助する(状況による)- UIの性質上、順序が重要でない情報に使う
column-count
使用時の読み順の落とし穴
マルチカラムレイアウトは、表示が左→右の列に流れていくように見えますが、実際の読み順は上から下です。
.grid {
column-count: 3;
}
- 左上 → 左下 → 次の列の上 という流れになり、スクリーンリーダーやキーボード操作では視覚と一致しません。
※タブ移動で順番が飛ぶように感じられることもあるので、フォームやナビゲーションには不向きです。
高さが不安定な要素の崩れ対策
画像+テキストのカードでよくある問題は、画像の読み込み前に高さが確定しないことによるレイアウトの揺れです。
対策案:画像に aspect-ratio を使う
.item img {
aspect-ratio: 4 / 3;
width: 100%;
object-fit: cover;
display: block;
}
aspect-ratio
で高さを予約し、表示時のジャンプを防止object-fit: cover
でトリミングしつつ、綺麗に収める
レスポンシブ対応の切り替え方法
スマホでは1列、PCでは3列以上にする場合、CSS GridでもColumnでも共通の調整が可能です。
Gridの場合
.grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
Columnの場合
.grid {
column-count: 1;
}
@media (min-width: 768px) {
.grid {
column-count: 3;
}
}
いずれもメディアクエリで列数を増減するだけで、実装は非常にシンプルです。
このように、見た目以上に地味な落とし穴やテクニックが多いUIですが、ポイントさえ押さえておけば、手軽に整ったグリッドレイアウトが実現できます。
実際どれを使うべき?現場目線の選択指針
ここまで紹介した3つの実装パターン、それぞれにメリット・デメリットがあります。
実務では、「どれが一番いいか」ではなく、「このケースならどれが最も適しているか」という視点で選ぶことが重要です。
Grid + grid-auto-flow: dense
を使うべきケース
- 要素の順序をある程度制御したい
- カードのサイズや配置を細かくコントロールしたい
- レイアウトの柔軟性を重視したい
おすすめのシーン:
- ECサイトの商品一覧
- 管理画面などでのカード型情報パネル
- タグで絞り込むような、頻繁に中身が変わるUI
column-count
を使うべきケース
- 実装をとにかく手早く済ませたい
- 見た目だけそれっぽく整えばOK
- 順序やフォーカス制御はそこまで気にしない
おすすめのシーン:
- ブログ一覧やニュースカード
- 画像だけで構成されるギャラリー
- 短命なキャンペーンLPなどの軽量実装
JavaScriptでの高さ補正を使うべきケース(例外)
- コンテンツによって高さが不安定すぎてどうにもならない
- IE11などの古い環境対応が必要(※2025年時点ではかなり限定的)
- 高さを完全に揃えることで一貫したUIを維持したい場合
おすすめのシーン:
- レガシー向けダッシュボード
- 厳密なビジュアル整合性が必要な広告・印刷用途系Webアプリ
決定のためのチェックリスト(YES/NOで選べる)
質問 | YESならこの方法 |
---|---|
要素の並び順が重要? | Grid(dense) |
表示順は気にしない? | Column |
カードの高さを完全に揃えたい? | JS補正 |
実装コストを最小限にしたい? | Column |
レスポンシブでカラム数を調整したい? | Grid or Column(どちらも可) |
メンテナンス性を重視したい? | Grid(CSSだけで完結) |
技術的な正解は複数ありますが、「どれが最小の実装コストで最大の見た目を出せるか」という判断軸で選ぶのが、プロダクションではもっとも現実的です。
最後に:プロの現場で選ぶなら、まずは「CSSだけで解決」から
Pinterest風レイアウトは見た目はシンプルですが、実は要素の高さがバラバラなUIをどう扱うかという、意外と奥の深い問題です。
フロントエンドの現場でこのレイアウトが出てきたら、まず以下のように考えるのがおすすめです:
- レイアウトの順序が重要 or UIの安定性を重視する場合 →
grid-auto-flow: dense
が最適 - 簡易表示・軽量実装でOKな場合 →
column-count
で時短+保守性◎ - 特殊事情(レガシー対応やピクセル単位の高さ揃え)がある場合 → JSの出番
そして重要なのは、**「完璧を求めすぎないこと」**です。
見た目のきれいさと実装コストのバランスを取りつつ、最低限のコードで最大の効果を出す、これこそがプロのコーディング。
今回紹介した方法は、すべて「今すぐ実務に使えるもの」ばかり。ぜひ次の案件で試してみてください。