gridとは二次元上でアイテムを好きに配置できるレイアウトモードです。
前の章でflex boxについて述べましたが、flex boxでの説明を思い出してください。

一次元は1つの方向に要素を並べる事が目的でしたが、二次元では2つの方向に要素を並べる事を目的とします。
これから解説するgirdは二次元レイアウトモードですので以下のようなレイアウトが可能になります。

webサイトをよく見てみるとグラフィカルなサイト以外のほとんどはgirdで表す事が可能な事にきずくかもしれません。
例えば以下はyahooですが、上の「gridが適している」という図の右側のレイアウトにsideの部分が増え、mainとsideの中に上の「gridが適している」という図 の左側のboxの並びが入れ子になったような構造をしています。

他にもgridで表現できるサイトは数多くあります。
webサイトを見る視点をかえ、「これはgridで再現できるか」という視点で見てみてください。きっと多くの発見がありあます。
そして、gridを学べば多くのサイトのレイアウトを再現する事ができますので是非gridを使いこなせるようになってください。
gridのメンタルモデル
girdは行と列で線を引き、マス目に区切ったエリアに要素を配置する事でレイアウトを実現すします。

列は同じ幅を共有してる必用があり、girdの線を途中で終える事もできません。
必ず列で同じ幅、同じ線の数を持つ必要があり、girdで再現できるレイアウトと再現できないレイアウトがあります。

右側のように横幅やgird線を自由に変更できないのならyahooのページの例で出したようなレイアウトは実現できないかと思ってしまうかもしれませんが、それは間違いで、規則正しいマス目でもyahooのレイアウトは可能です。
そう思ってしまうポイント、混合しやすい点は、gridと実際のコンテンツの配置を同じと考えてしまうからです。
今説明している線はあくまでガイドとなる線です。
そのガイドに沿ってコンテンツを配置するので、ガイドとコンテンツは異なります。
gridをさらに細かく分割し、各要素をこのように配置する事で再現可能です。

girdコンテナの制作
gridはflex boxと同じように並べ変えたいアイテムを囲う親を作り、その親にdisplay: gridを宣言する事で有効になります。
.parent { display: grid; }
gridコンテナ(.parent親要素)を制作すると以下のようなアイテムの並びとなります。
本来行と列の区分けを指定する必要がありますが、行と列を宣言しないと以下のようにデフォルトの値が適応されます。
<style> .parent { display: grid; } </style> <div class="parent"> <div class="item-1">item-1</div> <div class="item-2">item-2</div> <div class="item-3">item-3</div> </div>

flex boxと異なりgridはデフォルトでは縦に積まれます。
中のアイテムの高さはアイテムの高さに依存します。(フローレイアウトの動きとな同じです)
次に親のgridコンテナに高さを与えます。
<style> .parent { display: grid; height: 300px; } </style> <div class="parent"> <div class="item-1">item-1</div> <div class="item-2">item-2</div> <div class="item-3">item-3</div> </div>

高さを300pxにセットしました。
すると中の要素が均等に配置されます。
これは各アイテムに高さを指定していないのでgridの機能によって100pxずつ均等に配置されました。
gridでの横並び
gridはデフォルトでは縦並びです。
flex boxのようにgridで横並びにしたい場合はgrid-auto-flow: column;を宣言します。
これで要素は横並びになりますが、これはflex boxのような軸の概念は存在しません。
行が3つから1つになり、列が3つ制作され、そのマス目に沿って中のアイテムが配置されただけです。
<style> .parent { display: grid; grid-auto-flow: column; } </style> <div class="parent"> <div class="item-1">item-1</div> <div class="item-2">item-2</div> <div class="item-3">item-3</div> </div>
gridコンテナに横幅をセットしていない場合、コンテナ要素は画面いっぱいに広がり、中のアイテムは均等に分割されて配置されます。

gridのマス目の構築
これまではgirdのマス目については定義せずデフォルトの動きを見てきました。
ここからはマス目を独自に制作し好きなレイアウトを再現していきます。
grid-template-columnsを使用する事で列の数と列の大きさを指定する事が可能です。
See the Pen Untitled by tora (@-tora-) on CodePen.
grid-template-columnsに数字を2つ記載しましたのでこれは2つの列を作る意味になります。
そしてそれぞれ1列目が20%で2列目が80%のサイズを持ちます。
これでオリジナルののマス目を制作する事ができました。
ですが、この場合widthでpxを使って値を設定したようにマス目の幅は設定した値でロックされます。
その中の要素がどのような横幅かは気にしませんのでもし要素が大きければはみ出してしまいます。
See the Pen Untitled by tora (@-tora-) on CodePen.
この問題は下のfrでの指定方法で解決することができます。
柔軟な幅を指定する事ができるfr
マス目のサイズにfrユニットを使用するとアイテムのサイズに合わせて柔軟に対応してくれます。
See the Pen Untitled by tora (@-tora-) on CodePen.
1行目と2行目のブロックは全く同じスタイルを当てています。
ですが、中の要素の大きさによって1列目のサイズが変わっているのがわかります。
frを使用するとwidthで言うとmin-content: %;と同じような動きとなります。
今回の場合、列は2つで1列目の1単位と2列目の4単位を合わせて5単位分をgirdコンテナのinline方向(水平方向)で使用する事になります。
1列目は5単位分の1単位なので
(100 / 5) * 1 = 25%です。
2列目は5単位分の4単位なので
(100 / 5) * 4 = 75%
です。
そしてfrの場合、min-contentと同じで縮小に最小値を設ける事となり、1列目は25%いかには縮まりません。
複数の行
現状は列の指定マス目の構築しか行ていません。
列を2つに設定し、2つのアイテムをセットしているのでうまく動作していますが、この状態で複数のアイテムをセットするとどのような動きになるでしょうか。
以下のデモを見てください。
See the Pen Untitled by tora (@-tora-) on CodePen.
この場合、動きとしては初めに説明したデフオルトの動きと同じでそのまま縦積みになり、高さは中のコンテンツに依存します。
もしgridコンテナ(親)に高さを指定すれば今回は3行になっているので3分割される事となります。
これはgridが二次元軸でのレイアウトを目的としているため、あふれたアイテムは自動的に縦方向にセットされます。
flex boxとな異なり、改行されているわけではありません。
行方向のマス目の構築
grid-template-columnsと同じようにgrid-template-rowsを使用する事で行方向に独自のマス目を構築する事が可能です。
<style> .parent { display: grid; grid-template-rows: 50px 100px; } </style> <div class="parent"> <div class="item-1">item-1</div> <div class="item-2">item-2</div> </div>

行列のマス目を作る
grid-template-columnsとgrid-template-rowsを2つ合わせて使用すう事で行列のます目を制作します。
<style> .parent { display: grid; grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr 1fr; } </style> <div class="parent"> </div>

等間隔で3×5のマス目をつくりました。
リピート機能
先ほど1frを4つ記載し4つの等間隔の列を制作しましたが、数が多くなった場合毎回1frを記載する事は面倒です。
そんな時リピートグリッドを使用する事でまとめて楽に記載する事が可能です。
<style> .parent { display: grid; // grid-template-rows: 1fr 1fr 1fr; ←を以下のようにまとめて書く事ができます。 grid-template-rows: repeat(3, 1fr); // grid-template-columns: 1fr 1fr 1fr 1fr; ←を以下のようにまとめて書く事ができます。 grid-template-columns: repeat(4, 1fr); } </style> <div class="parent"> </div>
リピートは以下のように一部に使用する事もできます。
<style> .parent { display: grid; grid-template-rows: repeat(3, 1fr); grid-template-columns: 200px repeat(3, 1fr); } </style> <div class="parent"> </div>

gap
flex boxと同じようにgridでもgapをつかってアイテムどうしの余白を調整する事が可能です。
gap: 10px 30px;
gapの値に左が行方向、右が列方向と余白を設定可能です。
See the Pen Untitled by tora (@-tora-) on CodePen.
アイテムの配置
マス目の制作は完了です。
次は制作したマス目に沿ってアイテムを配置していきます。
アイテムの配置方法はいくつかありますがまずはエリア機能を使って配置していきましょう。
ここで制作するレイアウトは以下です。

このレイアウトを制作するためにはまず以下のようにマス目を制作します。
4 * 3の均等なマス目です。
<style> .parent { display: grid; width: 100%; height: 100vh; border: solid 1px #000; grid-template-rows: repeat(3, 1fr); grid-template-columns: repeat(4, 1fr); } </style> <div class="parent"> </div>
エリアでの配置
まずはマス目にエリア名を割り振ります。

このように左上からArea1, Area2, Area3となります。
エリアを作るためにはgrid-template-areasを使用します。
grid-template-areas: "area1 area1 area2 area2" "area1 area1 area2 area2" "area3 area3 area3 area3"; }
「ダブロクォーテーション」で囲った1行がマス目の1行を指します。
今回はマス目は3行あるので3行のダブロクォーテーション行を制作します。
その行の中に例えば「area1 area1 area2 area2」というようにスペースで区切った4つの文字列が各列を表します。
area1 area1というように同じ文字を複数記載すると記載した分のマス目がそのエリアになります。
そして次にarea1, area2, area3がどのアイテムなのかを宣言します。
アイテムにエリア名を紐づけるためにはgrid-areaを使用します。
.area1 { grid-area: area1; background-color: rgba(255, 0, 0, 0.3); } .area2 { grid-area: area2; background-color: rgba(0, 255, 0, 0.3); } .area3 { grid-area: area3; background-color: rgba(0, 0, 255, 0.3); }
See the Pen Untitled by tora (@-tora-) on CodePen.
トラックとラインでの配置
gridはトラックとラインで制作されています。
gridではエリアのほかにトラックとラインを使用してアイテムを配置する事も可能です。
トラックとはこれまでマス目と言っていたものを指します。
ラインとはそのトラック(マス目)の枠の事を指します。
トラックの枠にはそれぞれ番号が振られており、その番号を指定してアイテムを表示する場所を指定します。

例えばitem1を以下のような位置に表示したい場合

以下のように設定します。
<style> .parent { display: grid; grid-template-rows: repeat(3, 1fr); grid-template-columns: repeat(4, 1fr); } .item1 { grid-row: 1 / 3; // 行の指定 grid-column: 1 / 3; // 列の指定 background-color: rgba(255, 0, 0, 0.3); } </style> <div class="parent"> <div class="item1">item1</div> </div>
指定している箇所はgrid-rowとgrid-columnの部分です。
「/」スラッシュの前が開始地点のライン、スラッシュの後ろが終了地点のラインです。
row(行)は1番目のラインから3番目のラインまで、column(列)は1番目のラインから3番目のラインまでをセットする事で上の例のようなレイアウトを実装する事ができます。
See the Pen Untitled by tora (@-tora-) on CodePen.
spanを使った指定
スラッシュで区切る事で○番目のラインから〇番目のラインまでという指定をしましたが、spanを使用する事で〇番目から〇つ先のラインまでという指定の仕方が可能です。
書き方は「〇 / span 〇」です。
例えば1番目から2つ先のラインまでという指定の場合以下のように記載します。
grid-row: 1 / span 2; grid-row: 1 / 3; この書き方と同じ
ですので.itemに指定した
grid-row: 1 / 3;
grid-column: 1 / 3;
をspanの書き方で書くと以下のようになります。
grid-row: 1 / span 2; grid-column: 1 / span 2;
それぞれ1番目から2つ先なので3番目のラインまでですね。

書き方は違いますが、こちらと同じレイアウトです。
spanで記載しようが、spanを使わずに記載しようがどちらでもよいですが、よく見る書き方はspanを使用しない方法です。
[spanの応用]エリアをclassから柔軟に指定する
spanの書き方を応用してアイテムの表示エリアをclassから柔軟に操作する方法を紹介します。
girdをよく使用する場合はこの書き方はとても便利で、特に複数人でルールを持って開発する時に便利です。
また再利用性も高くなります。
spanを使った指定の方法では「span 〇」というようにspanの後にいくつ先のラインまでエリアを使用するか宣言しました。
このいくつ先の部分(spanの後ろの数字)を記載せず、スラッシュも記載しません。
〇 span
というように記載します。
すると、例えば「1 span」と記載すると1トラック分を使用したレイアウトとなります。
この特性を利用し、以下のようなcssを用意します。
.grid { display: grid; grid-template-columns: repeat(12, 1fr); } .col-1 { grid-column: 1 span; } .col-2 { grid-column: 2 span; } .col-3 { grid-column: 3 span; } .col-4 { grid-column: 4 span; } .col-5 { grid-column: 5 span; } .col-6 { grid-column: 6 span; } .col-7 { grid-column: 7 span; } .col-8 { grid-column: 8 span; } .col-9 { grid-column: 9 span; } .col-10 { grid-column: 10 span; } .col-11 { grid-column: 11 span; } .col-12 { grid-column: 12 span; }
多くのデザインではgirdを12に分割して考える事が多いです。
ですので12個の均等なトラックを用意します。
トラックが12個ですのでcol-〇というclassを1 ~12個用意し、それぞれ連番 + spanを記載します。
そして以下のデモのようにgridアイテムにcol-〇のclassを与えます。
See the Pen Untitled by tora (@-tora-) on CodePen.
codepenを開いてclass名を変更して実際にアイテムのレイアウトを変更してみてください。
デモを見るとcol-3とcol-9が与えられ、その比率でアイテムが並んでいる事がわかります。
col-3は12分割したトラックの3つ分を使用し、col-9は12分割したトラックの9つ分を使用します。
3対9のエリアが表示されたという事ですね。
このように与えるclassによって自由にアイテムのレイアウトを変更する事ができ、直観的にトラックの使用量でレイアウトを調整する事が可能となります。

ブラウザでのデバック
girdを実装する際に制作したトラックとラインを見たいという事があります。
gridのトラック、ライン、番号は通常は見る事はできませんがデベロップツールから確認する事が可能です。
デベロップツールを開いたら「レイアウト」の項目をクリックします。

すると以下のような項目が開きますので、オーバーレイの表示したの選択肢を「行番号を表示」にります。
そして、グリッドオーバーレイから表示したいgrid項目にチェックを入れる事でトラック、ライン、ラインの番号が表示されるようになります。
グリッドオーバーレイ項目は、現在しているgridアイテムのclass名が全て表示されますので見たいgridアイテムをチェックします。

borderをつける時のTips
gridにborderをつける際アイテムどうしがgap(余白)を持っていないと少し厄介なのですが、その場合の技を紹介します。
gridにborderをつけるというのは以下のようなデザインを再現したい場合の事を指しています。
See the Pen Untitled by tora (@-tora-) on CodePen.
アイテム2つが横並びになっていますが、それぞれのアイテムにborderが付いています。
ですが、左側のアイテムの右のborderと右側のアイテムの左のborderが重なってしまい、4pxの線ができてしまっています。

これを本来は重なりを失くして2pxにしたいのですが、ただたんにgridで並べるだけでは難しいです。
nth-childなどを使用し、2番目のアイテムの右のborderを消すというスタイルを当てる事で解決する事ができますが、〇番目と依存性が高く、複雑なレイアウトになった場合に厄介です。
そんな時は以下のようにすることで簡単に解決できます。
See the Pen Untitled by tora (@-tora-) on CodePen.
- parent要素の背景にborderの色(今回は#000)をセットします
- parentにborderの太さ分のpadding(今回は2px)をセットします
- parentにborderの太さ分のgap(今回は2px)をセットします
何をしているかというと、背景色の#000を透過させ、あたかもborderがあるかのように見せているだけです。

課題
gridを使って以下のようなガントチャートを制作してみましょう。

回答はこちらのページに記載してあります。