元ネタ
※元ネタサイト(//iketeru-nagashima.com/)に今アクセスしたら
「お使いのWindowsが壊れました」みたいな詐欺広告が出るのでお気を付けて…
こんにちは。怠惰な生活によって体重増えるばかりコーダーのKAGです。
本日は将来使えるレイアウト、CSS Gridを紹介します。
CSS Gridとは
ボックスの表示を制御するプロパティです。
縦と横の軸を指定して表示できるため、レイアウトの為に無駄に入れ子する必要がなくなります。
レイアウトのためのプロパティは他にもFloatとFlexBoxがありますが、これらは縦または横のどちらか1列しか自由に配置できません。
つまりどういう事?
- その名の通りグリッド状にレイアウトしたい時
- 高さや幅が異なる要素をタイル状に並べたい時
- 要素を縦横自由に配置したい時
等に真価を発揮します。
使い方
親要素に「display:grid」または「display:inline-grid」を指定すると、親要素は「グリッドコンテナー」になります。
ここで任意のサイズのグリッドトラックを作成します。
するとグリッドコンテナーにグリッドラインという線が引かれます。
親要素に包まれている子要素は「グリッドアイテム」になり、引かれたグリッドラインに沿って自由に配置ができるようになります。
説明聞いても意味わからん
ですよねぇ
図で説明した方が早そうなのでやってみましょう。
こういう事をします
CSS Gridの基本的なプロパティを使って、こういうデザインを作ってみます。
ブラウザ上の表示
HTML
<div class="parent"> <div class="child1">1</div> <div class="child2">2</div> <div class="child3">3</div> <div class="child4">4</div> <div class="child5">5</div> <div class="child6">6</div> </div>
CSS
/* グリッドコンテナー */ .parent{ display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; grid-gap: 12px; height: 490px; } /* グリッドアイテム */ .child1{ grid-row: 1/3; grid-column: 1/3; } .child2{ grid-row: 3/4; grid-column: 1/2; } .child3{ grid-row: 3/4; grid-column: 2/3; } .child4{ grid-row: 1/2; grid-column: 3/4; } .child5{ grid-row: 1/2; grid-column: 4/5; } .child6{ grid-row: 2/4; grid-column: 3/5; }
やってみよう
案ずるより横山やすし(byデーブ・スペクター)という事で早速いってみましょう。
HTMLを書く
まずグリッドレイアウトを表示するためのHTMLを書いていきます。
まず親要素を作り、その直下に要素を作ります。
今回は6つの要素が必要なので、直下に6つ作ります。
<div class="parent"> <div class="child1">1</div> <div class="child2">2</div> <div class="child3">3</div> <div class="child4">4</div> <div class="child5">5</div> <div class="child6">6</div> </div>
以上です。
これだけです。
無駄コンテナーを作る必要がありません。感動
グリッドコンテナーを作る
HTMLを書き終わったので、CSSを書いていきましょう。
今回は全体の高さが490px、幅はなり行きのレイアウトを作成します。
まずは親要素にdisplay:gridを指定します。
.parent{ display:grid; height:490px; }
これで親要素(このHTMLでいうと.parent)がグリッドアイテムを囲む箱であるグリッドコンテナーになりました。
同時に、子要素(.child1~6)はグリッドアイテムになり、これから引くグリッドラインに沿って自由に配置できるアイテムになります。
グリッドトラックを作る
上の例の通りのレイアウトにしたいので、グリッドコンテナー内に、縦方向に4つ、横方向に3つ分割した状態のグリッドトラックを作成します。
グリッドトラックは、グリッドの1行、または1列をさす言葉です。
グリッドトラックの作成には
- grid-template-columns
- grid-template-rows
プロパティを使います。
まずgrid-template-columnsプロパティで、グリッドを縦に分割します。
分割したい数だけ値を記入します。値の間はスペースをあけて入力します。
カラムの1列ごとのサイズも、ここで指定します。
.parent{ display:grid; grid-template-columns: 1fr 1fr 1fr 1fr; height:490px; }
今回は「fr」(fraction/比率)という単位でサイズを指定し分割しました。
幅や高さを相対的に指定できるすごいやつです。
例えば「grid-template-columns」に「2fr 1fr 1fr」を指定すると、2frのカラムは50%、1frのカラムは25%の幅で3分割されます。
grid-templateプロパティは、指定できる値が他にも色々あります。
以下のページが参考になりますのでご興味のある方は見てください。
この状態ではブラウザ上には何も表示されませんが、こんな風になっています。
グリッドコンテナー上に5本の縦線が引かれ、均等な幅で4つに分割されています。
グリッドコンテナーを分割しグリッドトラックを作ると、トラックとトラックの間に見えない線が引かれます。
これを「グリッドライン」と言います。
横はgrid-template-rowsプロパティを使って分割します。
(書き方、使える値はgrid-template-columnsプロパティと同じです)
.parent{ display:grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; height:490px; }
グリッドラインが縦に5本、横に4本引かれ、コンテナーがそれぞれ均等なサイズで縦4つ、横3つに分割されました。
以上の記述はgrid-templateプロパティで一括に指定する事もできます。
.parent{ display:grid; /* row(行)、column(列)の順で指定します rowとcolumnの値の間には、スラッシュを入力します */ grid-template: 1fr 1fr 1fr / 1fr 1fr 1fr 1fr; height:490px; }
グリッドアイテムを配置する
グリッドアイテムは、指定したグリッドラインに沿って配置します。
グリッドアイテムの配置には
- grid-row-start
- grid-row-end
- grid-column-start
- grid-column-end
プロパティを使います。
grid-row-○○はグリッドアイテムの行(横)、grid-column-○○はグリッドアイテムの列(縦)の配置を指定します。
今回の場合、1番目の子要素(.child1)は1番目の列と1番目の行に配置して、3番目の列と3番目の行まで表示したいので、こう書きます。
.child1{ grid-row-start: 1; grid-row-end: 3; grid-column-start: 1; grid-column-end: 3; }
ショートハンドを使って入力する事もできます。
grid-rowはグリッドアイテムの行(横)、grid-columnはグリッドアイテムの列(縦)の配置を一括で指定できます。
ショートハンドを使う場合は、グリッドの配置を開始する位置を左に、グリッドの配置を終了する位置を右に書きます。
.child1{ grid-row: 1/3; grid-column: 1/3; }
行グリッド、列グリッドの開始位置・終了位置を全てまとめて指定したい場合は、「grid-area」プロパティを使用します。
.child1{ /* 左から、 grid-row-start / grid-column-start / grid-row-end / grid-column-end の値 */ grid-area: 1 / 1 / 3 / 3; /* ややこしいな */ }
こんな感じで配置しました。
.child1{ grid-row: 1/3; grid-column: 1/3; } .child2{ grid-row: 3/4; grid-column: 1/2; } .child3{ grid-row: 3/4; grid-column: 2/3; } .child4{ grid-row: 1/2; grid-column: 3/4; } .child5{ grid-row: 1/2; grid-column: 4/5; } .child6{ grid-row: 2/4; grid-column: 3/5; }
行と列を一括で指定するgrid-rowとgrid-columnで書きました。
start~endまでプロパティを全部使うと煩雑すぎ、grid-areaで全部ショートハンドにするとややこしい(個人的に)ので、こう書いています。
ブラウザ上の表示はこうなります。
(わかりやすくなるよう色分けしています)
よりわかりやすくすると、こんな感じ
グリッド間の隙間を指定する
配置はできましたが、アイテムの間に隙間がなく詰まって見えます。
- column-gap
- row-gap
プロパティを追加して、隙間をあけます。
column-gapで列(縦)、row-gapで行(横)の隙間を指定します。
.parent{ display:grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; height:490px; /* 追加 */ column-gap: 12px; row-gap: 12px; }
表示はこんな感じ
↓よりわかりやすく
従来のFloatやFlexBoxですと、隣接する子要素の間に隙間をあけたい時には、子要素ごとに余白をつける必要がありました。
Gridは親要素にgapプロパティを付ければ、子要素に自動的に隙間をあけてくれます。
隙間ができるのはグリッドアイテムの間だけなので、グリッドコンテナーの四辺に余白はつきません。
隙間の幅はショートハンドで記述する事もできます。
一括で指定したい場合、grid-gapプロパティを使います。
.parent{
/* row(行)、column(列)の順で指定します */
grid-gap: 12px 12px;
/* どちらも同じ値の場合、省略もできます */
grid-gap: 12px;
}
完成
ね、簡単でしょ?
同じ事をやりたい時、たとえばFlexBoxでは
HTML
<div class="container">
<div class="parent1">
<div class="parent1-child1">1</div>
<div class="parent1-child2">2</div>
<div class="parent1-child3">3</div>
</div>
<div class="parent2">
<div class="parent2-child1">4</div>
<div class="parent2-child2">5</div>
<div class="parent2-child3">6</div>
</div>
</div>
CSS
.container{ display: flex; } .parent1, .parent2 { display: flex; flex-wrap: wrap; width: 50%; } .parent2{ margin: 0 0 0 12px; } .parent1-child1{ width: 100%; } .parent1-child1, .parent2-child3{ height: calc(((490px - 12px) / 3) * 2); } .parent1-child2, .parent1-child3, .parent2-child1, .parent2-child2 { height: calc((490px - 12px) / 3); } .parent1-child2, .parent1-child3{ width: calc(50% - 6px); } .parent1-child2{ margin: 12px 0 0; } .parent1-child3 { margin: 12px 0 0 12px; } .parent2-child1, .parent2-child2 { width: calc(50% - 6px); } .parent2-child2 { margin: 0 0 0 12px; } .parent2-child3 { margin: 12px 0 0 0; width: 100%; }
図解
こんな感じで親要素を2つ作り子要素を3つずつくるんで、親要素にFlexBoxを適用し、さらに上からコンテナーでくるみ、それにもFlexBoxを適用して親要素を横並びに…
と書かないとといけない
& 要素間に隙間を開けたかったり、最初の例のように子要素の大きさを変えながら配置したければ、さらに子要素に記述を足さないといけない
ので、書くのが面倒なうえ読みづらいコードになりますが、CSS Gridなら上記で示した通り、だいぶキレイに書けます。やったでぇ
いかがでしたか?
CSS Gridを知らない方に向けて書いてみましたが、私自身まだまだ理解が浅く、もっと効率の良い書き方があるかもしれません。
今回説明したプロパティはごく一部です。
CSS gridにはこの他にもたくさん便利なプロパティがあるので、自分で調べて探してみてくださ…
立ちはだかるIE11の壁
このまま「いかがでしたか?」で締めにかかろうとしたんですが、IE11が…
CSS Gridの実装はされているのですが古い仕様で実装され、挙動が違いすぎるので実質ほぼ互換性がないです。
なので、上で書いてきたCSSをそのまま実装すると、こうなります。
何も出ない
IE11を無視すれば使える事は使えますが、まだシェア的にIE11を無視するのは非常に難しいでしょう。
(Gulpとかに入れられる「Autoprefixer」というプラグインを使う手段もありますが、導入がちょっと大変&変換後手直しが必要な時もある)
ちなみに、Windows7にプリインストールされているIE11は2020年1月にサポートが終了しますが、Windows8.1のIE11は2023年、Windows10のIE11については2025年までサポートされます。
手強厚い…