【css】頻出するカード型UIスニペット

# グリッドで作るカード型UI

このような頻出するカード型レイアウトは今までdisplay: flex;を使用していましたが、最後の行の右揃えをするのに、疑似要素でコネコネする手間がありました。
グリッドの方が比較的簡単に直感的に実装できましたのでメモです。
参考：https://zero-plus.io/media/grid-layout/

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="LYmWrma" data-user="__m-sato__" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/__m-sato__/pen/LYmWrma">
  カード型UI</a> by __m-sato__ (<a href="https://codepen.io/__m-sato__">@__m-sato__</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## html
```html
    <ul class="grid_parent">
      <li class="grid_item">
        <img src="./imgs/img_01.jpg" alt="" />
        <h3>タイトルが入ります</h3>
        <p>テキストが入ります。テキストが入ります。テキストが入ります。</p>
        <a href="#">詳しくみる</a>
      </li>
      <li class="grid_item">
        <img src="./imgs/img_02.jpg" alt="" />
        <h3>タイトルが入りますタイトルが入ります</h3>
        <p>テキストが入ります。テキストが入ります。テキストが入ります。</p>
        <a href="#">詳しくみる</a>
      </li>
      <li class="grid_item">
        <img src="./imgs/img_03.jpg" alt="" />
        <h3>タイトルが入ります</h3>
        <p>
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
        </p>
        <a href="#">詳しくみる</a>
      </li>
      <li class="grid_item">
        <img src="./imgs/img_04.jpg" alt="" />
        <h3>タイトルが入ります</h3>
        <p>テキストが入ります。テキストが入ります。テキストが入ります。</p>
        <a href="#">詳しくみる</a>
      </li>
      <li class="grid_item">
        <img src="./imgs/img_02.jpg" alt="" />
        <h3>タイトルが入りますタイトルが入ります</h3>
        <p>テキストが入ります。テキストが入ります。テキストが入ります。</p>
        <a href="#">詳しくみる</a>
      </li>
      <li class="grid_item">
        <img src="./imgs/img_03.jpg" alt="" />
        <h3>タイトルが入ります</h3>
        <p>
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
          テキストが入ります。テキストが入ります。テキストが入ります。
        </p>
        <a href="#">詳しくみる</a>
      </li>
    </ul>
```

##  SCSS
```scss
@charset 'UTF-8';
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  width: 80%;
  margin: 50px auto;
}

h1 {
  text-align: center;
  margin: 50px 0;
}

li {
  list-style: none;
}

img {
  display: block;
  width: 100%;
  height: 180px;
  object-fit: cover;
}

.grid_parent {
  display: grid;
  grid-template-columns: 1fr;
  gap: 30px 20px;
  @media screen and (min-width: 560px) {
    grid-template-columns: 1fr 1fr;
  }
  @media screen and (min-width: 1024px) {
    grid-template-columns: 1fr 1fr 1fr;
  }
  @media screen and (min-width: 1440px) {
    grid-template-columns: 1fr 1fr 1fr 1fr;
  }
}

.grid_item {
  box-shadow: 0 2px 3px rgba($color: #000000, $alpha: 0.16);
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  h3,
  p,
  a {
    margin: 10px 20px;
    display: block;
  }
  a {
    text-align: center;
  }
}

```

下記部分で親要素をグリッドコンテナ化し、ブレイクポイントごとにカラム数を変化させています。
```scss
.grid_parent {
  display: grid; //グリッドコンテナ化
  grid-template-columns: 1fr; //sp時1カラム
  gap: 30px 20px;//上下 左右の余白
  @media screen and (min-width: 560px) {
    grid-template-columns: 1fr 1fr; //550px以上で2カラム
  }
  @media screen and (min-width: 1024px) {
    grid-template-columns: 1fr 1fr 1fr; //1024px以上で3カラム
  }
  @media screen and (min-width: 1440px) {
    grid-template-columns: 1fr 1fr 1fr 1fr; //1440px以上で4カラム
  }
}
```

下記部分、グリッドアイテムの中身の子要素の高さを揃えています。
```scss
.grid_item {
  box-shadow: 0 2px 3px rgba($color: #000000, $alpha: 0.16);
  display: grid; //グリッドアイテムの子要素もグリッドコンテナ化し中身の高さを揃える
  grid-template-rows: auto auto 1fr auto; //auto=コンテンツ高さ分、1fr=残りの余白
}
```

今回は使用していませんが、jsで中身の子要素すべての高さを揃えることも可能です。
今回のサンプルでいうと、h3のタイトル部分に
` <h3 class="js-get-height">タイトルが入りますタイトルが入ります</h3>`などとjsで取得するようにクラス付与して、一番高さのあるものに残りのタイトル要素の高さを揃えられます。

```js
const items = document.querySelectorAll(".js-get-height");
let maxHeight = 0;
for (let item of items) {
    if (item.offsetHeight >= maxHeight) {
      maxHeight = item.offsetHeight;
    }
}
for (let item of items) {
    item.style.height = maxHeight + "px";
}
```

subgridプロパティを使えば、cssのみで中身の子要素すべて綺麗に揃うみたいなので、対応ブラウザが増えていくのが待ち遠しいです。
https://qiita.com/oreo/items/5301dcb1128f20cc7d97