グリッドでよこ並び
CSSの「グリッドレイアウト」は、要素の中身を格子状に分割してできたマス目に子要素を好なように配置することができるレイアウトモデルです。displayプロパティにgridという値を指定することで利用できます。そんなグリッドレイアウトを使って、よこ並びしてゆきます!
グリッドは自由
フレックスボックスレイアウトは一次元のレイアウトモデルでしたが、グリッドレイアウトは「二次元」のレイアウトモデルって言われます。つまり縦にも横にも自由にレイアウトする事ができるということ。縦線と横線で区切った格子状のマス目に、任意の要素を割り当てていく感覚で、画面をレイアウトしてゆくことができます。なのできっと「よこ並び」だけじゃ役不足かもしれませんね…:ω。
ナビゲーションをよこ並び
まずは早速、例のナビゲーションにグリッドレイアウトを適用してみましょう!
ul要素にdisplayプロパティでgrid
を指定します。リンクボタンの隙間は、フレックスボックスの時と同じgapプロパティが使えます:)。
あれれ、隙間は空いたけど、縦に並んだままですね…:‹。フレックスボックスはデフォルトがよこ並びだったけれど、グリッドはデフォルトがたて並びになるんですねぇ:o。
グリッドをよこ並びになるようにするには、ul要素にさらにgrid-auto-flowプロパティで、column
と指定します。
もしくは、grid-template-columnsプロパティを使って、横方向にリンクボタンの数だけマス目を用意することもできます。ここでは、li要素が5つ横に並ぶように、auto
という値を5つ並べて指定します。
グリッドレイアウトの基本概念
displayプロパティでgrid
と指定した要素は「グリッドコンテナー」、その直接の子要素は「グリッドアイテム」という状態になります。
そして、コンテナー内に暗黙的に、下図のような格子状の体系を形成します。
要素を分割するグリッド線と、その線に囲われてできたグリッドセルから構成される、レイアウトの骨格となる“グリッド”が用意されます:)。
要素とは別に、レイアウトするための空間が用意されて、そこにグリッドアイテムを配置していくっていう仕組みなんです。つまり「グリッドを用意して、要素を配置する」っていうのが、グリッドレイアウトの一連の流れになります。:)
グリッドの用意
グリッドレイアウトを適用すると、まず最初に、自動配置ルールに従って暗黙的にグリッドが用意され、「行が埋まったら新しい行」という具合にグリッドアイテムを配置してゆきます。
上のサンプルでは、それを、grid-auto-flowプロパティでcolumn
と指定することで、「列が埋まったら新しい列」という流れ方に変えていたんですねー。
この状態で、要素がひとつ増えると、6つめの要素は新しい列へ配置されます。
一方、grid-template-columnsプロパティでは、明示的にグリッドを用意します。行に5列用意したことで、下図のような流れ方になっていたってわけ;)。
なので要素がひとつ増えると、6つめの要素は新しい行の最初の列へ配置されます。
要素の配置
グリッドアイテムは、デフォルトでは、自動配置ルールに従って、暗黙的に(順に)配置されてゆきますが、grid-columnプロパティを使って、明示的に配置することができます。
配置するグリッドの位置は、グリッド線の番号でもって指定します。
例えば下図のように、2つめの要素は「2番めと4番めの線」に挟まれた列に配置し、3の倍数の要素は「5番めと6番めの線」に挟まれた列に配置する、という具合。
CSSでは、「2番めと4番め」なら2 / 4
という風に、始めの線と終わりの線を/
で区切って指定します。こんな妙ちくりんなレイアウトも、グリッドレイアウトならば朝飯前なのです:D。
グリッドレイアウトについて、詳しくは下記ページを参照のこと。
グリッドレイアウトの基本概念 - CSS: カスケーディングスタイルシート | MDN
中央に配置する
フレックスボックスの時と同じように、justify-contentプロパティが使えます。center
と指定すれば、アイテムがコンテナーの左右中央に寄せて配置されます。
※grid-template-columnsプロパティでよこ並びした方も同じ。
リンクボタンのサイズを揃える
グリッドレイアウトでは、アイテムの横幅もコンテナー側に指定します。grid-auto-flowプロパティでよこ並びにした方は、grid-auto-columnsプロパティを使ってアイテムの幅を指定できます。ここでは、フレックスボックスの時と同じように、12em
と指定します。
grid-template-columnsプロパティでよこ並びにしている方は、auto
としていた値を、すべて12em
に書き換えます。けど、同じ値を何個も並べて書くのはなんだか冗長ですね…:‹。
こんな時はrepeat()関数が使えます。括弧の中に繰り返す回数と、繰り返す値をカンマ区切りで指定します。ここでは「12em
を5回繰り返す」ので、以下のように書けます:)。
リンクボタンの高さも、フレックスボックスの時と同じ要領で揃える事ができます。a要素の高さをli要素いっぱいに広げつつ、グリッドレイアウトを適用して、中のテキストを上下中央に配置します。
※grid-template-columnsプロパティの方も同じ。
レスポンシブにする
スマホではたて並びになるよう、メディアクエリを使って、768px以上の時だけよこ並びになるようにします。前述までのよこ並びにするためのスタイルを、メディアクエリの中に移動しちゃえばOKです:D。
ありゃ、768px以上の時に左右にハミ出ちゃってます…。リンクボタンが伸縮せずに、12em
のサイズに固定されてるみたいです:(。
フレックスボックスのflex-basisプロパティはあくまで基準となるサイズだから、固定されずにコンテナーに合わせて伸縮していたけれど、grid-auto-columnsプロパティで指定したサイズは、それとは違うんですね…:(。
グリッドコンテナーに合わせて伸縮するように、min()関数を使って、以下のように指定し直します。
伸縮するようになりましたね!
けど、よぉ〜く見てみると、ナビゲーションの横幅が若干、nav要素よりもハミ出てるように見えます…¦‹。どうやらgapプロパティで指定している隙間1px
が、リンクボタンの横幅20%
に含まれていないみたい…⁑|。フロートの時にも同じような事があったけれど、今回はパディングは使ってないので、box-sizingプロパティでは解決できなそう…。
100%から隙間4つ分の幅(4px)を引かなきゃいけないわけだから…、リンクボタンの横幅は、20%から4pxを5等分した幅を引けば良いって事。CSSで書くとcalc(20% - 4px / 5)
という事になります。
min()関数の中でも、calc()関数と同じように計算式を使う事ができるので、以下のように指定できます。
ナビゲーションが綺麗に収まりました:D!
fr
という単位
リンクボタンの幅に1frという値を使うことで、もっとシンプルに解決できます。fr
とは、グリッドレイアウトだけで使える単位。グリッドアイテムのサイズをコンテナー内のサイズの比率で以って指定できます。※fr
は「fraction(分数)」の略。
ここでは、12em
としていたところを、1fr
に置き換えます。それだけだとナビゲーションがビューポートいっぱいに広がっちゃうので、ナビゲーションの横幅を制限して、左右にマージンauto
を指定して中央に配置します。
ナビゲーションの横幅は、「リンクボタンの幅を12em
と指定してた時」と同じ幅になるように、calc(60em + 4px)
という横幅にしてます。
横幅の値が20%
だと、隙間分の誤差が出ちゃってましたが、1fr
なら、隙間分も考慮して、要素の幅を分割するので、ちょいハミの心配もありません:)。
「比率で分割する」というと、フレックスボックスのflex-growプロパティにも似ているけれど、flex-growプロパティは余白を分配するのに対して、fr単位は要素自体のサイズを比率で分割するので、ちょっと違います。
flex-basisプロパティの値を0
に指定して、コンテナーの横幅すべてが余白になれば、同じ結果になるんですけどね;p(下サンプル下段)。
グリッドレイアウトで商品一覧
ナビゲーションは、一方向だけのレイアウトだったので、そういうレイアウトならフレックスボックスの方がもっとシンプルにできた気がしますね…:3。グリッドでも出来ないことはないけど、勿体ない感じがします。
片や、商品一覧のような縦と横に並ぶレイアウトこそ、グリッドレイアウトの腕の見せ所なのです。:)
グリッドで商品一覧
商品一覧にもグリッドレイアウトを適用します!
横3列に並ぶ一覧なので、ここではgrid-template-columnsプロパティで、明示的に3列のグリッドを用意する作戦でいきます。横幅はグリッド専用の1fr
という値で、均等に配置します。
li要素にパディングを指定しているけれど、横幅の指定はないのでbox-sizing: border-box
の指定は要らないです。
きれーいに、かんたーんにレイアウトできちゃいましたXD!
レスポンシブにする
他の記事と同じく、メディアクエリを使って、429px以上の時は2列、768px以上の時は3列になるように調整します。と言ってもとってもシンプル。grid-template-columnsプロパティの繰り返す回数の値を、2
、3
と増やすだけです。
グリッドレイアウトだけの特別な値を使えば、メディアクエリを使わずに、一覧の列数を切り替えることもできます。
repeat()関数の繰り返す回数の指定に、auto-fit
という値を指定して、横幅には3列ちょうど収まるようにcalc(1024px / 3)
と指定。auto-fit
は、アイテムがコンテナーに収まる数として適用されます。