CSSサブグリッドを使って、カード内の要素の高さを揃える

LPや比較表などでカード型のリストをよく見かけますよね。
カードごとにテキストの長さや画像の高さが異なっている際、これまではdisplay: flex;を駆使して、何とかカード内の要素の高さを揃えていました。

ところが、最近はCSS サブグリッドを使うことで簡単に実装できるようですので、備忘録として残したいと思います!

目次

各ブラウザの対応状態

確認したところ、ほぼすべてのブラウザで動作するようです。
案件などで複数ブラウザの動作を保証する必要がある際も安心して使えそうですね。

MDN Web Docs
サブグリッド - CSS: カスケーディングスタイルシート | MDN CSS グリッドレイアウトの Level 2 は、 subgrid の値を grid-template-columns および grid-template-rows に追加しています。このガイドでは、サブグリッドでできること...

実装例

  1. カード群の親要素<div class=”card-wrap”>display: grid;を指定
  2. カードそのものである<div class=”card”>display: grid;grid-row: span 4;grid-tempalte-rows: subgrid;を指定

動作サンプル

※サンプル上ではボタン部分をpointer-events: none としているため、押下しても動作しません。

See the Pen CSS Subgrid by Yoshihiro Hotta (@yoshihiro-hotta) on CodePen.

HTML

<div class="content">
  <h2 class="title">カード一覧</h2>
  <div class="card-wrap">
    <div class="card">
      <div class="card__image-wrap">
        <img class="card__image" src="https://placehold.jp/350x350.png" alt="">
      </div>
      <h3 class="card__title">カード1のタイトル、カード1のタイトル</h3>
      <p class="card__text">カード1のテキスト、カード1のテキスト、カード1のテキスト、カード1のテキスト、カード1のテキスト</p> <a class="card__button"
        href="">カード1のボタン</a>
    </div>
    <div class="card">
      <div class="card__image-wrap">
        <img class="card__image" src="https://placehold.jp/450x350.png" alt="">
      </div>
      <h3 class="card__title">カード2のタイトル</h3>
      <p class="card__text">カード2のテキスト、カード2のテキスト、カード2のテキスト、カード2のテキスト、カード2のテキスト、カード2のテキスト、カード2のテキスト、カード2のテキスト</p> <a
        class="card__button" href="">カード2のボタン</a>
    </div>
    <div class="card">
      <div class="card__image-wrap">
        <img class="card__image" src="https://placehold.jp/250x350.png" alt="">
      </div>
      <h3 class="card__title">カード3のタイトル、カード3のタイトル、カード3のタイトル</h3>
      <p class="card__text">カード3のテキスト、カード3のテキスト</p> <a class="card__button" href="">カード3のボタン</a>
    </div>
  </div>
</div>

CSS

.content {
  width: 100%;
  max-width: 800px;
}

.title {
  text-align: center;
}

.card-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;
  width: 100%;
}

.card {
  display: grid;
  grid-row: span 4;
  grid-template-rows: subgrid;
}

.card__image-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
}

.card__image {
  width: 100%;
  height: auto;
  margin: 0 auto;
}

.card__title {
  margin: 0;
  text-align: center;
}

.card__text {
  margin: 0;
}

.card__button {
  display: block;
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
  padding: 10px 5px;
  color: #fff;
  font-weight: bold;
  text-align: center;
  text-decoration: none;
  background: #1d48bb;
  border-radius: 20px;
  transition: opacity .2s;
  box-sizing: border-box;
}

.card__button:hover {
  opacity: .8;
}

ポイント

<div class=”card”>に当てているCSSが特に重要です。

display: grid;を指定しつつ、grid-row: span 4; の数字部分を<div class=”card”>内の要素の数と合わせることで、表示を整えてくれます。

また、grid-template-rows: subgrid; を指定することで、カードの中の要素の位置がカード間で統一されます。
CodePenを開いていただき、該当部分をコメントアウトすると動きがよく分かるかと思います。

最後に

CSSサブグリッドを使えば、今後カードの実装で迷う場面が減らせそうです。

display: flex;も便利ですが、display: grid;もできることがたくさんあって良いですね。
今後も忘れがちな部分を備忘録として残していきたいと思います。

目次