subgridでリンクカード内の要素の高さを合わせる

目次

リンクカードのよくある問題

高さがずれているイメージ

画像やタイトル、説明文など複数の要素を持つカードでは、要素の高さが違うときに横並びのカードの高さがばらばらになってしまい見た目が悪くなるという問題が起こりがちです。

従来は高さを合わせるためだけに<table>タグを使ったり、JavaScriptで一番高い要素の高さを取得して他をそれに合わせて…という処理をすることが多かったですが、これだけのためにかかるコストが大きすぎました。

そこで、CSSに登場したsubgridによって、比較的簡単に実装できるようになりました。

subgridとは

subgridとは、グリッドレイアウトが入れ子構造になっているときに、親要素のグリッドを引き継いで使うことができる機能です。 2024年4月8日現在、すべてのモダンブラウザにサポートされています。

subgridの使い方

カードをまとめる親要素に対して、display: grid;を指定してグリッドレイアウトにします。

子要素もdisplay: grid;にして、grid-template-rows: subgrid;を指定します。 このとき、カード内の要素が親要素のグリッドの一行にすべて入る挙動になるので、子要素のカードにgrid-rows: span [カード内の要素数]として、要素分の行数を確保します。

/* グリッド用のスタイル */
.grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}

.card {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
  gap: 1rem;
}

.ignore {
  display: contents;
}

/* その他のスタイルは省略しています */

HTML

<ul class="grid-container">
  <li class="ignore">
    <a href="/" class="card">
      <img src="https://placehold.jp/400x200.png" alt="" width="400" height="200" />
      <h2>ページタイトル</h2>
      <p>ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文</p>
    </a>
  </li>
  <li class="ignore">
    <a href="/" class="card">
      <img src="https://placehold.jp/400x200.png" alt="" width="400" height="200" />
      <h2>ページタイトルページタイトルページタイトルページタイトル</h2>
      <p>ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文ページの説明文</p>
    </a>
  </li>
  <li class="ignore">
    <a href="/" class="card">
      <img src="https://placehold.jp/400x240.png" alt="" width="400" height="240" />
      <h2>ページタイトル</h2>
      <p>ページの説明文ページの説明文ページの</p>
    </a>
  </li>
</ul>

このようにすると、カード内の要素が一番高い要素に合うようになりました。

subgridを使って高さがあっているイメージ

subgridを使う要素は、外側のグリッドと直接の親子関係にないといけないので、間に要素が挟まる場合はdisplay: contents;を使用して無視をするか、子要素と同じようにsubgridを適用してグリッドの行をリレーする必要があります。 今回の例の場合はul>li>aとなっているので、間の<li>タグにはdisplay: contents;を適用しています。

以上

参考

サブグリッド - CSS: カスケーディングスタイルシート | MDN

CSS グリッドレイアウトの Level 2 は、 subgrid の値を grid-template-columns および grid-template-rows に追加しています。このガイドでは、サブグリッドでできること、いくつかの使用例と、この機能で解決されるデザインパターンを詳述します。