【CSS】 グリッドレイアウトを使いこなそう

グリッドレイアウトを用いることで、マス目に沿って要素を配置できます。HTMLのtableに対して柔軟に配置や大きさを制御できるようにしたもの、という感覚に近いです。

グリッドとは

グリッドとは、画面を画面を水平と垂直方向に複数分割したものです。要は長方形がある版の方眼紙のような分割です。

グリッドの例

グリッドレイアウトを利用することで、領域上のどれだけの大きさを使うかを簡単に指定できます。

グリッドを使う

それでは早速グリッドレイアウトを試していきましょう。

gridを指定

グリッドレイアウトを使うには、内側をグリッドにしたい要素にdisplay:grid;を指定します。

See the Pen css grid display by Totori (@souki202) on CodePen.

これでグリッドになりました。開発者ツールを見ると、グリッドであることがわかるアイコンが表示されています。

グリッドレイアウトが反映されているときの例

このgridボタンを押すと、該当箇所に何やら数値が表示されます。これはグリッドがどのように分割されているかを示す表示です。

gridボタンを押したときのグリッドの分割表示

勿論、gridの要素の中にgridを作ることもできます。tabletdの中にtableを入れるのと同じ感覚です。

サイズ指定

列のサイズ指定

列のサイズを指定するには、grid-template-columnsプロパティを用います。ここで、従来の単位に加え、新たにfrという単位が追加されています。

ここで、指定した値の数で画面は分割されます。frを使わない場合、分割した後に幅が余っていてもその領域は埋まりません。

div {
    grid-template-columns: 100px 200px 300px;
}

自動的に折り返されるなどが起こると、暗黙的にグリッドが生成されます。上の例だと5行になっていますが、同時に縦方向に5つのグリッドが生成されています。

従来のサイズ

従来のサイズでは、グリッドの大きさが指定したサイズになります。

See the Pen css grid column size by Totori (@souki202) on CodePen.

この例では、1列目は70px、2列目は120pxになります。列は2つであるとこのプロパティで明示しており、余った部分は利用されません。

fr

frは比率です。例えば

div {
    grid-template-columns: 2fr 1fr 3fr;
}

の場合、frの合計は6です。そのため、1列目は全体の6分の2、2列目は全体の6分の1、3列目は6分の3の大きさだけ占領します。つまり、2 : 1 : 3の比率で領域を使います。

See the Pen css grid columns fr by Totori (@souki202) on CodePen.

普通の指定と複合した場合、普通の指定だけはその指定した幅で、残りの領域をfrの値で取り分け、という形になります。

See the Pen css grid fr and legacy by Totori (@souki202) on CodePen.

この例では、中央は150px固定、残りの200px分を、合計3frから取り分けです。つまり、1列目は残り200pxのうち3分の2、3列目は200pxのうち3分の1の幅になります。

repeat

repeatを使うことで、同じ幅を並べられます。

div {
    /* この2つは同じ */
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-columns: repeat(3, 1fr);

    /* この2つは同じ */
    grid-template-columns: 3fr 100px 100px 2fr;
    grid-template-columns: 3fr repeat(2, 100px) 2fr;
}

行のサイズを指定

行のサイズを指定するには、grid-template-rowsプロパティを用います。幅のときと同様の挙動を取りますが、frを使用する際はgridの要素にheightの指定をすることを忘れないようにしましょう。

See the Pen Untitled by Totori (@souki202) on CodePen.

暗黙的なグリッドのサイズ指定

例えば、幅だけgrid-template-columnsで指定したとします。この時、要素数に折り返して2行目3行目が作成されると、縦方向 (各行) に暗黙的なグリッドが作成されます。

その暗黙的なグリッドの大きさは、grid-auto-columnsgrid-auto-rowsで指定します。

See the Pen css grid auto rows by Totori (@souki202) on CodePen.

minmaxで最小の大きさを指定

グリッドの大きさを指定する際は、高さは最小100、コンテンツが多ければもっと大きく、としたい場合があります。その場合、値にminmaxを使用します。

See the Pen css grid minmax by Totori (@souki202) on CodePen.

上の例では、行の高さは最小75px、それ以上はautoという指定になっています。実際、1列目は最小値の75pxで、2列目は内容が多いものがあるため、高さが大きくなっていることが分かります。

もちろん、minmax(auto, 300px)とすれば、最大300pxという指定似できます。

min-heightなどは動作しません。

行と列のサイズ指定、という言い方からも分かる通り、flexと違って要素ごとのサイズ指定はできません。行単位、列単位での指定です。

要素の並ぶ位置を指定

flexのときと同じように、align-itemsalign-selfを用います。下の例では、FFFalign-selfが設定されていないため、align-itemsの揃え方が適用されています。

See the Pen css grid align by Totori (@souki202) on CodePen.

意味
stretch引き伸ばす
start開始位置に揃える。横並びなら上に、縦並びなら左に揃う
center中央に揃える
end終了位置に揃える

グリッドの座標に対して配置

これまでの例では、要素を自動で並べました。次は、指定した座標に要素を置いてみます。つまり、複数のセルにまたがって配置できます。

グリッドの座標は、次のようになっています。

グリッド分割時の座標

つまり、左上を基準に1からスタートということです。

See the Pen css grid position by Totori (@souki202) on CodePen.

上の図の通りに置いてみました。余った領域には座標を指定していない残りの要素が並ぶことが分かります。この座標の配置は、まるで2Dゲームでxy座標を指定するかのような感覚ですね。

ここで、grid-column-startgrid-row-endなどはstartendを1つにまとめることができます。

div {
    /* startが1、endが3 */
    grid-column: 1 / 3; 

    /* startが3、endが6 */
    grid-row: 3 / 6;
}

上の例でわかるとおり、行列の各個数は指定していませんが、自動でグリッドが作成されています。grid-template-columnsなどでの指定がなければ、startend、要素の折返しによる列の増加などから自動で計算してくれるということです。

gridの自動分割例

さらに、startendを指定した結果、1マス分しか取得しない場合はendを省略できます。

div {
    /* どちらもstartが1、endが2 */
    grid-column: 1;
    grid-column: 1 / 2;

    /* どちらもstartが3、endが4 */
    grid-row: 3;
    grid-row: 3 / 4;
}

縦横1マスの各領域はグリッドセル、複数のグリッドセルをあわせた領域はグリッド領域と呼びます。

Excel方眼紙のような使い方はやめましょう。レスポンシブなWebサイトを作りづらくなります。

要素の領域を重ねる

まるで2Dゲームのように座標を指定できると書きました。もし座標がかぶっても、普通に重なって表示されます。

See the Pen css grid pile up by Totori (@souki202) on CodePen.

AAAの一部とBBBの一部がかぶっています。AAAはxが1 ~ 6, yが1 ~ 3、BBBはxが2 ~ 5、yが2 ~ 5なので、かぶります。

通常は後の要素が上に表示されますが、表示順を調整したい場合は従来どおりz-indexで重なりを指定すると良いです。

絶対座標を使う

position: absoliteを用いると、マス目の位置や大きさを使用しつつ、座標のズレを作ることができます。

See the Pen css grid absolute by Totori (@souki202) on CodePen.

ここで注意点として、topleftでは開始座標が動くだけなので、終了座標(grid-xx-end)は変化しないということに注意が必要です。

また、要素の中身が少ない場合、leftbottomの指定がないと、中身が収まる程度の最小の大きさになるということにも注意が必要です。試しに下の例で、.item.item-bbbbottomrightを削除してみると小さくなることが分かります。(直接操作できます)

See the Pen css grid absolute2 by Totori (@souki202) on CodePen.

grid-xx-startなどを使わない場合、いつものabsoluteの挙動になります。つまり、普段のabsoluteに加えてgrid-xx-startなどが利用できる、ということです。

セルにスペースを設ける

普通の要素はmarginで要素ごとのスペースを指定しますが、gridではcolumn-gaprow-gapを用います。

See the Pen css grid gap by Totori (@souki202) on CodePen.

あくまで要素間の間隔なので、上の例の通り、親領域と子要素の間にスペースができるわけではありません。そこにスペースが欲しい場合、親要素側に普通にpaddingを付けましょう。

グリッド数を自動にする

grid-template-columnsなどで行や列の数を明示しましたが、親要素の幅などによって可変にしたいと言うのはよくあります。その場合、auto-fillを使用します。

See the Pen css grid autofill by Totori (@souki202) on CodePen.

グリッドの分割は、幅などから自動で計算されます。

auto-fillでの自動分割例

minmaxと組み合わせる

repeat(auto-fill, minmax(100px, 1fr))のようにすることで、要素の大きさを可変にしつつ、多く要素を詰め込むように要素が収まる数も可変になります。

See the Pen css grid autofill2 by Totori (@souki202) on CodePen.

上の例では、最小110pxという指定で、できるだけ多く要素を詰め込もうとしています。もし1行に4つ詰め込んでしまうと幅が110pxを下回ってしまうため、1行に最も多く詰め込める列の数は3です。

上の例でBBB..が飛び出していることからも分かる通り、flexのような、要素の中身の大きさに応じるものではありません。

flexとの違い

flexは、要素をどの方向に、どのような基準でどのような大きさにして並べるかを指定します。gridは、方眼紙のように分割した領域上に、どの場所にどんな大きさで配置するかを指定します。

つまりflexは並び方を、gridはグリッド上の位置と大きさを重視しています。

これらはどちらか一方だけを使用する、というものではありません。gridの中にflexがあったりなど、使い分けが重要です。

次元の違い

flexは1次元です。つまり、一方向に並び、改行されたらまた新しいflexの領域が作成されます。つまり、1列または1行にどのように並ぶかを指定します。

gridは2次元です。つまり、2次元領域でどのように並べたり、座標に配置するかを指定します。

行ごと、列ごとの指定で十分ならflex、行列どちらも制御が要るならgridが良いでしょう。

例えばflexでは、1~n-1行目はspace-betweenで、n行目で中途半端な数の場合にそれまでの列と揃えて並べる、といったことは不可能です。

大きさの管理の違い

flexは、要素ごとに柔軟に大きさを調整できます。例えば横方向に並べる場合、高さは要素ごとに指定できます。その位置揃えも要素ごとに指定できます。

See the Pen css align-self by Totori (@souki202) on CodePen.

gridはHTMLのtableのようにサイズが管理されます。つまり、高さや幅が使用するマス単位で揃います。特定の要素だけ列か行の片方を特定のサイズにするといったことはalign-selfなどである程度できますが、flexと比べると柔軟性は大きく低下します。

See the Pen css grid minmax by Totori (@souki202) on CodePen.

まとめ

gridを用いることで、2次元空間上に要素を並べることができます。また、x, y座標を指定するような感覚で要素の領域を指定でき、要素同士を重ねることも容易です。

flexとの違いを把握して、うまく使い分けられるようになりましょう!

役に立ったらシェアしよう!