グリッドレイアウトの作り方を解説〜display: gridのチュートリアル〜
前田 大地
CSSのグリッドレイアウト(display: grid
)は、これまでのfloatやflexでは難しかったレイアウトを実現可能にします。gridについて解説している記事はたくさんあるので、今回は具体的にflexでは不可能なレイアウトを例に出して、それを実際にgridで作ってみたいと思います。
目次
レイアウトの種類と変貌
まずはおさらいとして、コーディングでレイアウトを作るときにどんな手法が使えるのか、その種類についてざっくり解説しておきます。
tableレイアウト
むかしむかし、おじさんがおにいさんだった頃に一般的だったレイアウト手法です。tabelタグのrowspan属性とcolspan属性を駆使してレイアウトの骨格を作ります。「そもそもtableはレイアウトのためのタグではない」と怒られて誰も使わなくなりました。divをdisplay: table
にすれば問題無いとする説もありますが、面倒なので誰もやりません。
floatレイアウト
「Web標準」なんて言葉が登場した頃に主流となったレイアウト手法です。主要ブラウザがflexに対応するまでは、floatによる段組みが主流でした。要素を左右に振り分けることでレイアウトを実現します。必ず最後にfloatを解除しないと崩れてしまうため「clearfix」というテクニックが流行しました。今は、わざわざレイアウトのためにfloatを使う意味がありません。
flexレイアウト
主要ブラウザがCSS3に対応したことで主流となったレイアウト手法です。縦もしくは横の一方向に要素を並べるのが得意で、多くのケースで利用されます。tableやgridと違い、格子状にエリアを区切らないため、ブログの「タグクラウド」みたいに、子要素の幅がバラバラなものをキレイに並べることができます。感覚的にはちょっとだけfloatに近いかも。
gridレイアウト
この中では一番新しいレイアウト手法です。IEのサポートが終了したことでようやく実務で使えるようになりました。格子状のグリッドを作ってその中に子要素を配置していきます。イメージとしてはtableに近く、複数行をまたぐようなセルが必要なときには、flexではなくgridを使います。gridは、flexの進化版というわけではないので、適材適所で使い分けるようにしましょう。
今回、gridでこれを作ります
一見すると、とくに何の変哲もないレイアウトに見えます。しかし、スマホとPCのレイアウト差異が、ちょうどHTML上で要素をグルーピングしずらくなっていて、flexで実現するのは大変難しいレイアウトになっています。
完成形
ちなみに、完成形のコードは以下のとおりです。gridにはいろいろな書き方があるので、この通りに書く必要はありません。思い通りに表示させることができたらそれが正解です。
See the Pen grid layout by Daichi Maeda (@daichifive) on CodePen.
実際に作ってみる
それでは、実際に作っていきましょう。
心の目でグリッドを捉える
gridレイアウトは、格子状にエリアを区切る必要があるため、縦横のラインで分割できるデザインにしか適用できません。まずはデザインを凝視して、心の目でデザイン上にグリッド線を引きましょう。
できました。今回は、たまたまPCとスマホでどちらも6分割されましたが、例えばスマホは6分割でPCは8分割のように、分割数が異なっていても大丈夫です。この段階で、あまりにもグリッドが複雑になるようなら、別の方法を使ったほうが早い可能性もあります。
エリアに名前を付ける
分割されたエリアに、名前をつけていきます。こちらも慣れれば脳内で行えます。
HTMLを組む
ざっくり脳内で雰囲気が掴めたら、HTMLを作ります。デザインを見る限りでは、「画像」→「タイトル」→「説明文」→「リンク」の順番に並べておくのが構造的に良さそうです。
<div class="item"> <div class="item_img"><img src="image.jpg" alt=""></div> <h3 class="item_ttl">タイトル</h3> <p class="item_txt">説明文説明文・・・</p> <p class="item_link"><a href="#">リンク</a></p> </div>
CSSでgridの骨格を作る
HTMLが完成したら、CSSでdisplay: grid
によるレイアウトを作っていきます。まずはスマホから。
grid-template-areasを使って、6分割したそれぞれのエリアに名前を割り当てます。先程、脳内で事前にエリア名をつけてありますから、それをそのまま使います。
.item { display: grid; grid-template-areas: "img ttl" "txt txt" "link link"; }
改行やスペースを入れて見やすくしておくと、後で見たときに嬉しい気持ちになれます。
各要素に名前を設定する
gridの子要素に対しては、grid-areaを使って「どのエリアに表示させるか」を設定します。親要素のgrid-template-areasで設定したエリア名の中から、表示させたいエリアを選んでください。
.item_img { grid-area: img; } .item_ttl { grid-area: ttl; } .item_txt { grid-area: txt; } .item_link { grid-area: link; }
細かい表示を調整する
すでにレイアウトはできましたので、あとはデザインと同じになるよう各要素を微調整します。いろいろと調整したCSSが以下になります。
.item { display: grid; grid-template-areas: "img ttl" "txt txt" "link link"; grid-template-columns: 45% 45%; justify-content: space-between; align-items: center; } .item_img { grid-area: img; } .item_ttl { grid-area: ttl; margin: 0; } .item_txt { grid-area: txt; margin: 1em 0 0; } .item_link { grid-area: link; margin: 1em 0 0; }
ざっと説明すると、grid-template-columnsで列の幅を設定して、justify-contentで両端揃えにしています。また、align-itemsで「img」と「ttl」が上下の中央で揃うようにしています。
PCのレイアウトを設定する
スマホの表示ができましたので、次にPCでの表示を作ります。こちらも脳内の図を参考にしてgrid-template-areasを設定します。また、いくつかのプロパティを上書きして、PCの表示に合わせます。
@media (min-width: 768px){ .item { grid-template-areas: "img ttl" "img txt" "img link"; grid-template-rows: max-content 1fr max-content; align-items: start; } }
CSSはスマホから
時と場合にもよりますが、一般的にはスマホのほうがシンプルなレイアウトになるケースが多いです。スマホのCSSを書いた後、PCのCSSをメディアクエリで上書きしたほうが、コード量が少なくてすみます。
frって何?
上記CSSには「fr」という単位が使われています。frとは、「余った幅や高さを分配する比率」です。
幅や高さが明示的に指定されているものは、その幅や高さがそのまま適用されます。その上で、余った幅や高さが「fr」の比率によって分配されます。
ちょっとややこしいので例を挙げます。
grid-template-colums: 100px 1fr 1fr;
上記の場合、全体の幅から100px引いた余りを、1:1で分配します。全体の幅が500pxだったら、100px、200px、200pxとなります。
それを踏まえて今回のコードの該当箇所を見てみると、、
grid-template-rows: max-content 1fr max-content;
全体の高さからmax-contentとmax-contentを引いた余りが、1frに対して分配されます。
・・・まあ、このへんの仕様については、gridレイアウトについて解説している別のサイトをご覧ください。そのほうがきっと分かりやすいです。
完成!
これで、gridによるレイアウトの完成です!
右上にある「EDIT ON CODEPEN」をクリックすると別タブで確認できますので、画面幅を変えたりしてレイアウトを確認してみてください。
See the Pen grid layout by Daichi Maeda (@daichifive) on CodePen.
こういうのは慣れなので、実際にgridを使っていろいろ試しているうちに憶えます。私は、floatからflexに移行するとき、慣れるまでけっこう大変でしたが、今はとくに難しく考えることもなく使えています。まあ、そんなものです。
それでは、gridに乾杯!