0. はじめに
この記事では、CSS Grid Layoutの基本は知っているという前提で、いろいろな場面を想定して更なる使い方を書いていきたいと思います。
この記事は4部構成の中の 場面別編 です。
CSS Grid Layout を極める!(基礎編)
CSS Grid Layout を極める!(場面別編) ←これ
作成中:CSS Grid Layout を極める!(アルゴリズム編)
作成中:CSS Grid Layout を極める!(番外編)
トラックの大きさを柔軟に指定したい (grid-template-rows / grid-template-columns)
トラックの幅・高さの指定は grid-template-rows
/ grid-template-columns
で行いました。
基礎編では px
を主に使いましたが、他にも様々なものが使えます。そして、以下で挙げる値は自由に組み合わせて使うことが出来ます。
#container {
grid-template-columns: 100px 50% max-content 1fr auto minmax(100px, 500px);
}
※尚、このセクションの内容は非常に奥が深いので、アルゴリズム編(作成中)で別途詳しく書いていきたいと思います。
- 長さ, %
px, %, em, vh, vw などの単位はもちろん、mm, cm, in, pt, pc, ch, rem, vmin, vmax など、width
に使えるような長さの単位が大体使えます。
これらをcalc()
関数の中で組み合わせて使うことも出来ます。
- max-content, min-content
そのトラック内のすべてのアイテムの max-content あるいは min-content の値を算出し、その最大値を採用します。
max-content, max-content は他のCSSプロパティにも用いることができますので、詳細の説明は割愛します。
参考:Qiita: CSS での横幅 (width) 、高さ (height) の指定にキーワード値を使う
- auto
そのトラックのアイテムの内容や、他のトラックとの兼ね合いで、適切な大きさになります。
- fit-content(長さ)
autoに近いですが、"長さ"の指定が若干作用します。
- minmax(min, max)
トラックの最小幅および最大幅を指定できます。min および max には上に挙げてきた値を入れることが出来ます。
#container {
display: grid;
grid-template-columns: 100px minmax(600px, 800px);
}
- fr
すべての他のトラックの大きさが決定してもまだなおコンテナに余裕がある場合に、frを指定しているトラックがその比率で残りのスペースを占有します。
#container {
display: grid;
grid-template-columns: 100px 1fr 2fr;
}
frを指定しているトラックが1つだけならば、そのトラックが残りのスペースをすべて占有することになります。
#container {
display: grid;
grid-template-columns: 200px 1fr;
}
アイテムを自動的に配置したい
基礎編では、ラインの番号で指定したり、エリアに名前を付けて指定したりして、アイテムを配置していきました。
確かにこれらの方法でもアイテムは配置できますが、すべてのアイテムにCSSで位置を指定するのは面倒ですよね。
このセクションでは、そういったアイテムの配置のCSSを省略して書ける(かもしれない)ということを説明します。
※尚、このセクションの内容は非常に奥が深いので、アルゴリズム編(作成中)で別途詳しく書いていきたいと思います。
自動的に配置
アイテムに grid-row
/ grid-column
/ grid-area
を特に指定しなかった場合には、左上から順にアイテムが埋まっていきます。
<div id="container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
</div>
#container {
display: grid;
grid-template-rows: 200px 100px;
grid-template-columns: 200px 100px 100px;
}
自動的に配置する方向を列方向にする (grid-auto-flow)
上の例のように、普通は行方向から順にアイテムが埋まりますが、これはコンテナの grid-auto-flow
プロパティの初期値が row
だからです。
コンテナに grid-auto-flow: column;
を指定することで列方向から順にアイテムが埋まります。
#container {
display: grid;
grid-template-rows: 200px 100px;
grid-template-columns: 200px 100px 100px;
grid-auto-flow: column;
}
拡張したトラックの大きさを指定する (grid-auto-rows / grid-auto-columns)
グリッドのトラックの大きさの指定は grid-template-rows
/ grid-template-columns
で定義出来ますが、場合によってはアイテムがこれらのプロパティで指定したよりも外側に来ることがあります。
- アイテムに
grid-row
/grid-column
を指定して、わざと外側のエリアを指定した場合 - アイテムに
grid-row
/grid-column
を指定しないが、アイテム多すぎてが定義したグリッドよりもはみ出る場合 - そもそもコンテナに
grid-template-rows
/grid-template-columns
を指定していない場合
その場合のトラックの大きさを指定するプロパティが、grid-auto-rows
/ grid-auto-columns
です。コンテナに指定します。
- grid-auto-rows: はみ出たアイテムの行トラックの大きさを指定する
- grid-auto-columns: はみ出たアイテムの列トラックの大きさを指定する
例:grid-auto-rows: 50px;
はみ出たアイテムの縦の高さを50pxにする。
また、半角スペースで区切って指定すると、指定した大きさを繰り返します。
例:grid-auto-rows: 50px 100px;
はみ出たアイテムの縦の高さを 50px -> 100px -> 50px -> 100px ...と繰り返す。
トラックの大きさの指定には、先程のセクションに挙げたものが使えます。
<div id="container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div> <!-- Gは特にアイテムの位置を指定していないが、アイテムの数が多いのではみ出る -->
<div id="itemH">H</div> <!-- Hはアイテムの位置を grid-template-rows/columns の外に指定している -->
</div>
#container {
display: grid;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
grid-auto-rows: 30px 50px;
}
#itemH {
grid-row: 4; grid-column: 2;
}
コンテナに grid-template-rows
/ grid-template-columns
を指定していない場合は、全てのグリッドが grid-auto-rows
/ grid-auto-columns
の大きさになります。
<div id="container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
</div>
#container {
display: grid;
grid-auto-rows: 70px;
grid-template-columns: 100px 100px 100px 100px;
}
自動的に配置(span使用)
grid-row
/ grid-column
でラインの番号を指定する代わりに、隣接するセルをいくつ跨いで占有するかだけを指定することが出来ます。
grid-row: span ○○;
のように指定します。
#item {
/* 行方向に2セル、列方向に3セルを占有する。どこに配置するかは自動的に決まる。 */
grid-row: span 2;
grid-column: span 3;
}
この場合も、左上から順にアイテムが埋まっていきます。
<div id="container">
<div>A</div>
<div id="itemB">B</div>
<div>C</div>
<div>D</div>
<div>E</div>
</div>
#container {
display: grid;
grid-template-rows: 200px 100px;
grid-template-columns: 200px 100px 100px;
}
#itemB {
grid-row: span 2;
}
固定の配置と自動的な配置を混ぜる
grid-row
/ grid-column
/ grid-area
を使った固定の配置と、自動的な配置を混ぜることもできます。
その場合、固定配置のアイテムが先に配置され、その後に左上から空いたスペースに自動的な配置のアイテムが配置されていきます。
<div id="container">
<div>A</div>
<div id="itemB">B<br>(固定)</div>
<div>C</div>
<div id="itemD">D<br>(固定)</div>
<div>E</div>
<div>F</div>
</div>
#container {
display: grid;
grid-template-rows: 200px 100px;
grid-template-columns: 200px 100px 100px;
}
#itemB {
grid-row: 1; grid-column: 1;
}
#itemD {
grid-row: 2; grid-column: 2;
}
denseでなるべく敷き詰める (grid-auto-flow)
自動的な配置の方法は左上から順にアイテムが埋まっていきますが、左上から順番であるがゆえに、場合によってはスペースが空いてしまう場合があります。
<div id="container">
<div>A</div>
<div id="itemB">B</div>
<div id="itemC">C</div>
<div>D</div>
<div>E</div>
</div>
#container {
display: grid;
grid-template-rows: 100px 100px 100px 100px;
grid-template-columns: 100px 100px 100px;
}
#itemB {
grid-row: span 2; grid-column: span 2;
}
#itemC {
grid-row: span 2; grid-column: span 2;
}
そこで grid-auto-flow: dense;
を指定することで、開いているスペースをなるべく埋めるという指定にすることが出来ます。
<div id="container">
<div>A</div>
<div id="itemB">B</div>
<div id="itemC">C</div>
<div>D</div>
<div>E</div>
<div>F</div>
</div>
#container {
display: grid;
grid-template-rows: 100px 100px 100px 100px;
grid-template-columns: 100px 100px 100px;
grid-auto-flow: dense;
}
#itemB {
grid-row: span 2; grid-column: span 2;
}
#itemC {
grid-row: span 2; grid-column: span 2;
}
尚、自動的に配置する方向を列方向にするにもあるように、grid-auto-flow
は、自動的な配置の方向を変える役目もあります。
同時に指定したい場合は grid-auto-flow: column dense;
のように記述します。
自動的な配置の順番を変える (order)
自動的な配置は、通常 HTML順に左上から配置されていきますが、order
プロパティを使うことでその順番を変更できます。
<div id="container">
<div id="itemA">A</div>
<div id="itemB">B</div>
<div id="itemC">C</div>
<div id="itemD">D</div>
<div id="itemE">E</div>
<div id="itemF">F</div>
</div>
#container {
display: grid;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
}
#itemA { order: 4; }
#itemB { order: 2; }
#itemC { order: 1; }
#itemD { order: 3; }
#itemE { order: 6; }
#itemF { order: 5; }
トラックの大きさの指定を繰り返したい
固定回数繰り返す (repeat(n, ...))
トラックの幅の指定は grid-template-rows
/ grid-template-columns
で行いますが、トラックの数が多くなると書くのが面倒になりますね。
#container {
display: grid;
grid-template-rows: 100px 50px 100px 50px 100px;
grid-template-columns: 100px 100px 100px 100px 100px;
}
繰り返しの部分は repeat(繰り返す回数, トラックの幅)
というふうにかけます。
#container {
display: grid;
grid-template-rows: repeat(2, 100px 50px) 100px;
grid-template-columns: repeat(5, 100px);
}
コンテナの大きさに合わせて繰り返す (repeat(auto-fill | auto-fit, ...))
例えば、「100px のトラックを、横に詰めれるだけ詰めたい!」ということもありますね。
こういう場合は repeat(auto-fill | auto-fit, トラックの幅)
を使います。
<div id="container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
</div>
#container {
display: grid;
grid-auto-rows: 100px;
grid-template-columns: repeat(auto-fill, 100px);
}
auto-fill
と auto-fit
は非常に似ていますが、1つだけ違う点があります。
-
auto-fit
では、アイテムが配置されなかったトラックは無くなります。
これは、後述する justify-content
などを用いたときに特に分かりやすいです。
justify-content: center;
とするとグリッド全体が真ん中に寄るのですが、auto-fillだとうまく中央に寄らないことがあります。
#container {
display: grid;
grid-auto-rows: 100px;
grid-template-columns: repeat(auto-fill, 100px);
justify-content: center; /* グリッド全体を中央に寄せる設定 */
}
これは、auto-fill
だとアイテムが配置されないトラックの幅も確保してしまうためです。
auto-fit
を用いると、アイテムが配置されなかったトラックは無くなるので、ちゃんと中央に寄ります。
#container {
display: grid;
grid-auto-rows: 100px;
grid-template-columns: repeat(auto-fit, 100px);
justify-content: center; /* グリッド全体を中央に寄せる設定 */
}
グリッドやアイテムの位置をいろいろ指定したい
グリッドの位置を指定する (justify-content / align-content)
デフォルトでは、コンテナ内のグリッドは左上に寄っています。
#container {
display: grid;
width: 500px;
height: 300px;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
}
justify-content
/ align-content
を指定すると、コンテナ内のグリッドの位置を調整できます。コンテナのスタイルとして記述します。
- justify-content: グリッドの横方向の位置を指定する
- align-content: グリッドの縦方向の位置を指定する
指定できる値は、start
/ center
/ end
などがあります。
#container {
display: grid;
width: 500px;
height: 300px;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
justify-content: center; /* 横方向は中央に */
align-content: end; /* 縦方向は下端に */
}
セル同士に隙間をあける(1) (grid-row-gap / grid-column-gap)
デフォルトだとセル同士は隙間なく隣接しますが、grid-row-gap
/ grid-column-gap
を指定するとセル同士の間に隙間を開けることが出来ます。コンテナのスタイルとして記述します。
#container {
display: grid;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
grid-row-gap: 10px;
grid-column-gap: 30px;
}
セル同士に隙間をあける(2) (justify-content / align-content)
justify-content
/ align-content
を使ってセル同士に隙間をあけることも出来ます。
アイテムの位置を一気に指定する (justify-items / align-items)
デフォルトでは、アイテムはエリア内をすべて占めるように配置されます。(auto
)
全てのアイテムをセル内のどこかに寄せたい場合は、justify-items
/ align-items
を使います。コンテナのスタイルとして記述します。
- justify-items: 全てのアイテムの横方向の位置を指定する
- align-items: 全てのアイテムの縦方向の位置を指定する
#container {
display: grid;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
justify-items: center;
align-items: end;
}
アイテムの位置を個別に指定する (justify-self / align-self)
全てのアイテムの位置を指定するのではなく、個別で指定することも出来ます。
justify-self
/ align-self
を使います。アイテムのスタイルとして記述します。
- justify-self: アイテムの横方向の位置を指定する
- align-self: アイテムの縦方向の位置を指定する
#itemA {
justify-self: center;
align-self: end;
}
【チートシート】グリッドやアイテムの位置の調整
※justify-items
/ align-items
は、コンテナに指定して全てのアイテムの位置を指定する
アイテムの位置を数値で指定する (margin)
単純に margin
を用いることで、エリアの4辺からの距離を指定することが出来ます。
#itemA {
margin: 10px 20px 30px 10px;
}
また、負のマージンを指定することで、アイテム同士を重ねることも出来ます。
#itemA {
margin: 10px -20px -30px 10px;
}
アイテムの位置を絶対位置で指定する (position)
コンテナの子孫要素に position: absolute;
が指定されており、その位置決めの基準がコンテナである(≒コンテナにposition: static;
以外が指定されている)場合、その要素はアイテムと同じように grid-row
/ grid-column
/ grid-area
で位置指定ができます。
top
/ bottom
/ left
/ right
で位置指定をすると、ラインからの距離を指定することが出来ます。
また、このように配置された要素は他のアイテムの配置に影響しません。
<div id="container">
<div id="itemA">A</div> <!-- itemA は position: absolute; -->
<div>B</div> <!-- itemB 以降は特に位置を指定しないが、itemA を避けるということはない。 -->
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
</div>
#container {
position: relative; /* コンテナが位置決めの基準である */
display: grid;
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
}
#itemA {
position: absolute; /* 子要素を position: absolute; にする */
grid-row: 1 / 3;
grid-column: 2 / 4;
top: 10px;
bottom: 10px;
left: 10px;
right: 10px;
opacity: .8;
}
なお(実用性があるかどうかは別にして)、この場合のアイテムは必ずしもコンテナの子要素である必要はありません。
<div id="container">
<div>B<div id="itemA">A</div></div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
</div>
アイテムの重なり順序を指定する (z-index)
margin
や position: absolute;
の例のように、アイテム同士が重なることがあります。
その場合の重なり順序を変えるには z-index
を用います。
なお、アイテムに position: relative;
などを指定する必要はありません。単純に z-index
を指定するだけで重なり順序を制御できます。
ショートハンドで書きたい
今まで説明してきたプロパティにはショートハンドで書けるものが多々あります。
うまく使えばタイピング量を減らせるので、積極的に使っていきたいです。
grid-template
コンテナに指定します。
grid-template-rows
/ grid-template-columns
/ grid-template-areas
のショートハンドですが、指定方法にかなり癖があります。
書き方に2パターンがあり、どちらの方法も使い所があるので覚えておくとお得です。
- 書き方1: <grid-template-rows> / <grid-template-columns>
単純に grid-template-rows
と grid-template-columns
をスラッシュで区切って続けて書くという書き方です。
#container {
grid-template-rows: 100px 100px;
grid-template-columns: 200px 200px 200px;
/* ↓こう書ける */
grid-template: 100px 100px / 200px 200px 200px;
}
この方法では grid-template-areas
は指定できませんが、初期化(grid-template-areas: none;
)されてしまうので注意です。
つまり、grid-template-areas
を同時に指定したいなら、後に記述するべきです。
/* BAD */
#container {
grid-template-areas:
"areaA areaB areaC"
"areaD areaE areaF";
grid-template: 100px 100px / 200px 200px 200px;
}
/* GOOD */
#container {
grid-template: 100px 100px / 200px 200px 200px;
grid-template-areas:
"areaA areaB areaC"
"areaD areaE areaF";
}
- 書き方2: アスキーアートですべてを同時に指定
この書き方は非常に独特です。
grid-template-areas
→ grid-template-rows
→ grid-template-columns
の順に書いていくと分かりやすいです。
まず、エリアの名前(grid-template-areas
)を書いて…
#container {
grid-template:
"areaA areaB areaC"
"areaD areaE areaF"
}
次に、それぞれの行の高さ(grid-template-rows
)を文字列の後に書いて…
#container {
grid-template:
"areaA areaB areaC" 100px
"areaD areaE areaF" 100px
}
最後に、それぞれの列の幅(grid-template-columns
)をスラッシュの後に書きます。
#container {
grid-template:
"areaA areaB areaC" 100px
"areaD areaE areaF" 100px
/ 200px 200px 200px;
}
慣れさえすれば、エリアの名前と各トラックの大きさが視覚的に分かり、非常に見やすいプロパティの指定方法となります。
なお、エリアの名前の指定は必須ですが、行の高さと列の幅は指定しなくても構いません。
grid
コンテナに指定します。
grid-template-rows
/ grid-template-columns
/ grid-template-areas
/ grid-auto-rows
/ grid-auto-columns
/ grid-auto-flow
/ grid-row-gap
/ grid-column-gap
、つまりコンテナに指定できるグリッド関係のプロパティほぼ全てのショートハンドです。
(grid
で grid-row-gap
/ grid-column-gap
を指定する方法はありませんが、同時に初期化されてしまいます。)
これには書き方が2パターンあります。
- 書き方1:
grid-template
と同じ指定をする
grid
には grid-template
と全く同じ書き方を指定することが出来ます。
ただし、grid-template
では初期化しないようなプロパティ(grid-auto-rows
/ grid-auto-columns
/ grid-auto-flow
/ grid-row-gap
/ grid-column-gap
)も初期化するという点で異なります。
ですので、これもプロパティの書き順に注意が必要です。
/* BAD */
#container {
grid-row-gap: 10px;
grid:
"areaA areaB areaC" 100px
"areaD areaE areaF" 100px
/ 200px 200px 200px;
}
/* GOOD */
#container {
grid:
"areaA areaB areaC" 100px
"areaD areaE areaF" 100px
/ 200px 200px 200px;
grid-row-gap: 10px;
}
- 書き方2: トラックの大きさとauto-flowの方向を同時に指定する
この書き方では、次のどちらか一方の指定をすることになります。
-
grid-auto-flow: row;
にして、grid-auto-rows
とgrid-template-columns
を指定する
grid: auto-flow <grid-auto-rows> / <grid-template-columns>;
-
grid-auto-flow: column;
にして、grid-template-rows
とgrid-auto-columns
を指定する
grid: <grid-template-rows> / auto-flow <grid-auto-columns>;
なんか一見ややこしいことをしているように思えますが、実に理にかなっています。特にアイテム数が不定の場合によく分かります。
grid-auto-flow: row;
の方を指定した場合、アイテムは左上から行方向に並んでいき、下に伸びていきます。
この時、列のトラック数は固定数、行のトラック数は可変になります。
つまり、固定数の列トラックに対しては grid-template-columns
でトラック数と大きさを指定、
可変数の行トラックに対しては grid-auto-rows
で(トラック数は不明だけど)大きさを指定する、ということが同時に出来ます。
#container {
display: grid;
grid: auto-flow 100px / 200px 200px 200px;
}
grid-auto-flow: column;
の方を指定した場合にも同様のことがいえます。
また、auto-flow
に続けて dense
を書くこともできます。
#container {
display: grid;
grid: auto-flow dense 100px / 200px 200px 200px;
}
grid-row / grid-column
実は grid-row
/ grid-column
もショートハンドです。
grid-row: 1 / 2;
をロングハンドで書くと、grid-row-start: 1; grid-row-end: 2;
です。
grid-column: 1 / 2;
をロングハンドで書くと、grid-column-start: 1; grid-column-end: 2;
です。
このようにロングハンドで書くと非常に長くなるので、grid-row-start
などを使うことはあまりないでしょう。
grid-area
今まで grid-area
はエリアの名前を指定するために使っていましたが、
実は grid-row
/ grid-column
のショートハンドでもあります。
grid-row: A / B; grid-column: C / D;
→ grid-area: A / C / B / D;
grid-row: A; grid-column: C;
→ grid-area: A / C;
のように書けます。
#itemA {
grid-row: 1 / 2;
grid-column: 3 / 4;
/* ↓このようにも書ける */
grid-area: 1 / 3 / 2 / 4;
}
#itemB {
grid-row: 1;
grid-column: 3;
/* ↓このようにも書ける */
grid-area: 1 / 3;
}
このように、grid-row
/ grid-column
のライン指定が共に1つである時は非常に見やすくなります。
また、逆に grid-area
でのエリア指定を grid-row
/ grid-column
を使って書くことも出来ます。
#itemA {
grid-area: areaA;
/* ↓このようにも書ける */
grid-row: areaA;
grid-column: areaA;
}
grid-row: areaA;
などがどういう意味を表すのかは、番外編(作成中)でまたご紹介したいと思います。
grid-gap
grid-row-gap
/ grid-column-gap
のショートハンドです。
半角スペースで区切って2つの値を指定しますが、同じ値の場合は1つだけ書くこともできます。
#container1 {
grid-row-gap: 10px;
grid-column-gap: 20px;
/* ↓このようにも書ける */
grid-gap: 10px 20px;
}
#container2 {
grid-row-gap: 10px;
grid-column-gap: 10px;
/* ↓このようにも書ける */
grid-gap: 10px;
}
【チートシート】CSS Grid Layout のプロパティまとめ
要素別
- コンテナに指定するプロパティ
|プロパティ名|値の例|ショートハンド|
|:--|:--|:--|:--|
|display|grid or inline-grid||
|grid-template-rows|100px 200px|★grid-template
★grid|
|grid-template-columns|300px 400px|★grid-template
★grid|
|grid-template-areas|"areaA areaB"
"areaA areaC"|★grid-template
★grid|
|★grid-template|100px 200px / 300px 400px
or
"areaA areaB" 100px
"areaA areaC" 200px
/ 300px 400px||
|grid-auto-flow|row
or
column dense|★grid|
|grid-auto-rows|10px 20px|★grid|
|grid-auto-columns|30px 40px|★grid|
|grid-row-gap|3px|★grid-gap
★grid|
|grid-column-gap|5px|★grid-gap
★grid|
|★grid-gap|3px 5px||
|★grid|(grid-template と同じ)
or
auto-flow 100px / 200px 200px||
|justify-content|start or center or end||
|align-content|start or center or end||
|justify-items|start or center or end||
|align-items|start or center or end||
- アイテムに指定するプロパティ
|プロパティ名|値の例|ショートハンド|
|:--|:--|:--|:--|
|grid-row-start|1|★grid-row
★grid-area|
|grid-row-end|2|★grid-row
★grid-area|
|★grid-row|1 / 2 or 1||
|grid-column-start|3|★grid-column
★grid-area|
|grid-column-end|4|★grid-column
★grid-area|
|★grid-column|3 / 4 or 3||
|★grid-area|areaA
or
1 / 3 / 2 / 4
or
1 / 3||
|justify-self|start or center or end||
|align-self|start or center or end||
|z-index|1||
|order|1||
個人的によく使うものは太字にしました。