CSS
CSS3
CSSDay 7

CSS Grid Layoutで作るレスポンシブな表組み3パターン

アイレット株式会社デザインセクションでマークアップエンジニアとして働いているくどうです。CSS Advent Calendarに参加するのは初めてですがどうぞよろしくお願いします。

概要

CSS Grid Layoutを使っていますか?
たしかに最初はとっつきにくいし、1frってなんだよ…と言いたくなる気持ちもわかります。
しかし、こういった新機能は我々の新しい武器です。少々癖が強い武器ですが、忍者の手裏剣、ブルース・リーのヌンチャク、あるいは宮本武蔵の二刀流よろしく使いこなすことができれば強力でしかも超cool。超wavyでごめんね。ならばマスターするしかないですね!

というわけで本日はレスポンシブな表組みレイアウトを3パターン紹介します。

実践

PC時は横、スマホ時は縦に行方向が変化する表組みレイアウト

画像 

まずはディスプレイ幅の広いPCの時には行方向を横に、ディスプレイ幅の狭いスマホ時には行方向を縦(=列方向)に可変する表組みを作ってみます。
このレイアウトは<table>要素やdisplay:tableを使っても実装できますが、CSS Grid Layoutを使えば下記のようなコードで実現できます。

html
<div class="box">
  <div class="box__itmes box__title">坊ちゃん</div>
  <div class="box__itmes">
      親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び
  </div>
  <div class="box__itmes box__title">徒然草</div>
  <div class="box__itmes">
      つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
  </div>
  <div class="box__itmes box__title">爆発音がした</div>
  <div class="box__itmes">
      後ろで大きな爆発音がした。俺は驚いて振り返った。後ろで大きな
    </div>
  <div class="box__itmes box__title">Lorem</div>
  <div class="box__itmes">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </div>
</div>
css
.box {
  display: grid;
  width: calc(100% - 10px);
  border-top: 4px solid #96ceb4;
  border-left: 4px solid #96ceb4;
  grid-auto-rows: auto;
  grid-template-columns: 20% 80%;
}

@media screen and (max-width: 736px) {
  .box {
    grid-auto-columns: auto;
  }
}

.box__itmes {
  font-size: 16px;
  padding: .25rem .25rem .25rem .5rem;
  color: #444;
  border-right: 4px solid #96ceb4;
  border-bottom: 4px solid #96ceb4;
  background-color: #fff;
}

@media screen and (max-width: 736px) {
  .box__itmes {
    grid-column: 1 / 3;
  }
}

.box__title {
  font-size: 18px;
  font-weight: bold;
  background-color: #ffeead;
}

プレビュー

PC時は横並び3列、スマホ時は1列づつ折り返すレイアウト

画像
こちらはReally Responsive Tables using CSS3 FlexboxのようにFlexboxレイアウトでも実装できますが、グリッドレイアウトだとこうなります。

html
<div class="box">
  <div class="box__itmes box__title">坊ちゃん</div>
  <div class="box__itmes">
    親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び 
  </div>
  <div class="box__itmes box__title">徒然草</div>
  <div class="box__itmes">
    つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。 
  </div>
  <div class="box__itmes box__title">爆発音がした</div>
  <div class="box__itmes">
    後ろで大きな爆発音がした。俺は驚いて振り返った。後ろで大きな 
  </div>
</div>
css
.box {
  display: grid;
  width: calc(100% - 10px);
  border-top: 4px solid #96ceb4;
  border-left: 4px solid #96ceb4;
  grid-auto-rows: auto;
  grid-template-columns: 1fr 1fr 1fr;
}

@media screen and (max-width: 736px) {
  .box {
    grid-auto-columns: auto;
  }
}

.box__itmes {
  font-size: 16px;
  padding: .25rem .25rem .25rem .5rem;
  color: #444;
  border-right: 4px solid #96ceb4;
  border-bottom: 4px solid #96ceb4;
  background-color: #fff;
}

@media screen and (min-width: 737px) {
  .box__itmes:nth-child(1),
  .box__itmes:nth-child(2) {
    grid-column: 1;
  }
  .box__itmes:nth-child(3),
  .box__itmes:nth-child(4) {
    grid-column: 2;
  }
  .box__itmes:nth-child(5),
  .box__itmes:nth-child(6) {
    grid-column: 3;
  }
  .box__itmes:nth-child(odd) {
    grid-row: 1;
  }
  .box__itmes:nth-child(even) {
    grid-row: 2;
  }
}

@media screen and (max-width: 736px) {
  .box__itmes {
    grid-column: 1 / 4;
  }
}

.box__title {
  font-size: 18px;
  font-weight: bold;
  background-color: #ffeead;
}

プレビュー
うーんこれはもう少しシンプルに書くことができるかも😅

Masonryレイアウト

スクリーンショット 2017-12-05 18.02.31.png
縦方向に高さの異なる要素を並べるレイアウトです。昔はこのレイアウトをCSSだけで実現することは不可能だった(rowspancolspanと空<td>を多用したテーブルならいけるのかも?)のでJSライブラリのMasonryを使うことが多かったですよね。

しかし、今はCSS Grid Layoutがあります。
下記CSSの.boxgrid-gapプロパティを、.box__itemsborder-radiusプロパティを設定すれば、まさにPinterestのようなMasonryレイアウトがCSSのみで表現できます。

html
<div class="box">
  <div class="box__items">1</div>
  <div class="box__items">2</div>
  <div class="box__items">3</div>
  <div class="box__items">4</div>
  <div class="box__items">5</div>
  <div class="box__items">6</div>
  <div class="box__items">7</div>
</div>

css
.box {
  display: grid;
  margin: 10px;
  border-top: 4px solid #96ceb4;
  border-right: 4px solid #96ceb4;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(50px, auto);
}

.box__items {
  display: flex;
  color: #96ceb4;
  border-bottom: 4px solid #96ceb4;
  border-left: 4px solid #96ceb4;
  background-color: #ffeead;
  align-items: center;
  justify-content: center;
}

.box__items:nth-child(1) {
  grid-row: 1 / 4;
  grid-column: 1;
}

.box__items:nth-child(2) {
  grid-row: 1 / 3;
  grid-column: 2;
}

.box__items:nth-child(3) {
  grid-row: 1 / 4;
  grid-column: 3;
}

.box__items:nth-child(4) {
  grid-row: 4 / 7;
  grid-column: 1;
}

.box__items:nth-child(5) {
  grid-row: 3 / 7;
  grid-column: 2;
}

.box__items:nth-child(6) {
  grid-row: 4 / 6;
  grid-column: 3;
}

プレビュー

所感

以上3パターンの表組みレイアウトを紹介させていただきました。一つ一つは<table>要素やdisplay:table、またはdisplay:flex、あるいはJSを使って実現できるものでしたが、CSS Grid Layoutならこの全てを表現できます。ということは、さまざまなパターンの表組みの共通部分を使いまわせるわけで、そうした副次的なメリットも実務においては大きいと思います。

なおデメリットはIE系ブラウザで表示に苦労することです。IEは一応10からdisplay:gridに対応してはいるのですが、-ms-prefixつきのgrid関連プロパティ群は独自仕様が多く、またドキュメントも少ないので苦労します。また、iOS Safariもv10.3からの対応となっており、それ以前のものだと確実に崩れますので、お仕事でコーディングされる場合はcaniuseでの対応ブラウザ確認が必須になるかと思います。
追記: 2018年5月、AutoprefixerのアップデートによりIE系のGrid Layoutがサポートされました。詳しくは

最後に「もっといいやり方があるよ!」というご意見などございましたらお気軽にコメントください:bow: