とほほのグリッド入門
- グリッドとは
- 基本的グリッド
- 方向指定
- 名前付きエリア
- 名前付きエリアの横幅・高さ指定
- エリア名と高さ・横幅を個別に指定
- デフォルトの高さと横幅
- 開始ライン・終了ライン
- 名前付きライン
- ギャップ(gap)
- オートフロー(auto-flow)
- スパン(span)
- オート(auto)
- フラクションサイズ(fr)
- 最小最大(minmax)
- 最大コンテント(max-content)
- 最小コンテント(min-content)
- フィットコンテント(fit-content())
- リピート(repeat())
- 密集(dense)
- サブグリッド(subgrid)
- グリッドレイアウト
- CSSプロパティ
- 文法
- リンク
グリッドとは
- CSSで実現される、フレックスボックスと双璧をなすレイアウト機能です。
- 英語の grid には格子、碁盤目などの意味があります。
- IE を除くほとんどのブラウザで利用可能です。(→ サポート状況)
- グリッドの親要素を コンテナと呼びます。
- グリッドの子要素を アイテム と呼びます。
- コンテナを格子上に区切った区画を セル と呼びます。
- セルの間の境界線を ライン と呼びます。
- 複数のセルを矩形型に連結したものを エリア と呼びます。
- アイテムをライン番号やエリア名を用いてグリッド上に配置していきます。
基本的グリッド
縦横のセルを定義し、左上から順番にアイテムを並べていく方式です。display: grid はこの要素がグリッドの親コンテナであることを示します。grid プロパティはグリッドコンテナ内のセルを定義します。下記の例では縦方向に 2rem 2rem の2行、横方向に 4rem 4rem 4rem の3列、6個のセルを定義しています。
.container-grid {
display: grid;
grid: 2rem 2rem / 4rem 4rem 4rem;
}
<div class="container-grid"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> <div class="my-box">E</div> <div class="my-box">F</div> </div>
方向指定
grid-auto-flow はアイテムをセルに並べていく方向を指定します。column を指定すると行が埋まると、列を増やしていきます。
.container-grid-with-flow {
display: grid;
grid: 2rem 2rem / 4rem 4rem 4rem;
grid-auto-flow: column;
}
名前付きエリア
grid でエリアに名前を付け、アイテムに配置先のエリア名を指定する方式です。下記の例では、上部にヘッダ(header)、下部にフッタ(footer)を配置、中央を メニュー(menu)、メイン(main)、サイドバー(side) の3エリアに分割し、子アイテムをエリア名でそれぞれの場所に配置しています。
.container-named-area {
display: grid;
grid: "header header header"
"menu main side"
"footer footer footer";
.header { grid-area: header; }
.menu { grid-area: menu; }
.main { grid-area: main; }
.side { grid-area: side; }
.footer { grid-area: footer; }
}
<div class="container-named-area"> <div class="my-box header">Header</div> <div class="my-box menu">Menu</div> <div class="my-box main">Main</div> <div class="my-box side">Side</div> <div class="my-box footer">Footer</div> </div>
名前付きエリアの横幅・高さ指定
grid でエリア名を指定する際に、エリアの高さ、横幅を指定することができます。下記の例ではエリアの高さを 2rem, 4rem, 2rem、横幅を 4rem, 16rem, 4rem に指定しています。高さに auto を指定すると最小の高さ、横幅に auto を指定すると最大の横幅となります。
.container-named-area-with-length {
display: grid;
grid: "header header header" 2rem
"menu main side" 4rem
"footer footer footer" 2rem
/ 4rem 16rem 4rem;
.header { grid-area: header; }
.menu { grid-area: menu; }
.main { grid-area: main; }
.side { grid-area: side; }
.footer { grid-area: footer; }
}
<div class="container-named-area-with-length"> <div class="my-box header">Header</div> <div class="my-box menu">Menu</div> <div class="my-box main">Main</div> <div class="my-box side">Side</div> <div class="my-box footer">Footer</div> </div>
エリア名と高さ・横幅を個別に指定
grid-template-areas, grid-template-rows, grid-template-columns はエリア名、高さ、横幅を個別に指定します。
.container-named-area-with-length-2 {
display: grid;
grid-template-areas:
"header header header"
"menu main side"
"footer footer footer";
grid-template-rows: 2rem 4rem 2rem;
grid-template-columns: 4rem 16rem 4rem;
.header { grid-area: header; }
.menu { grid-area: menu; }
.main { grid-area: main; }
.side { grid-area: side; }
.footer { grid-area: footer; }
}
<div class="container-named-area-with-length-2"> <div class="my-box header">Header</div> <div class="my-box menu">Menu</div> <div class="my-box main">Main</div> <div class="my-box side">Side</div> <div class="my-box footer">Footer</div> </div>
デフォルトの高さと横幅
grid-auto-rows, grid-auto-columns はセルの高さや横幅が指定されない場合のデフォルトサイズを指定します。
.container-with-default-size {
display: grid;
grid-template-areas:
"itemA itemB itemC"
"itemD itemE itemF";
grid-auto-rows: 2rem;
grid-auto-columns: 10rem;
.itemA { grid-area: itemA; }
.itemB { grid-area: itemB; }
.itemC { grid-area: itemC; }
.itemD { grid-area: itemD; }
.itemE { grid-area: itemE; }
.itemF { grid-area: itemF; }
}
<div class="container-with-default-size"> <div class="my-box itemA">A</div> <div class="my-box itemB">B</div> <div class="my-box itemC">C</div> <div class="my-box itemD">D</div> <div class="my-box itemE">E</div> <div class="my-box itemF">F</div> </div>
開始ライン・終了ライン
アイテムの開始ラインと終了ライン番号を指定する方式です。セル番号ではなく、線の番号で指定します。grid-area には、縦方向の開始線 / 横方向の開始線 / 縦方向の終了線 / 横方向の終了線 を指定します。
.container-line-number {
display: grid;
grid: 2rem 2rem / 4rem 4rem 4rem 4rem;
.itemA { grid-area: 1 / 1 / 3 / 2; }
.itemB { grid-area: 1 / 2 / 2 / 4; }
.itemC { grid-area: 2 / 2 / 3 / 3; }
.itemD { grid-area: 2 / 3 / 3 / 4; }
.itemE { grid-area: 1 / 4 / 3 / 5; }
}
<div class="container-line-number"> <div class="my-box itemA">A</div> <div class="my-box itemB">B</div> <div class="my-box itemC">C</div> <div class="my-box itemD">D</div> <div class="my-box itemE">E</div> </div>
名前付きライン
下記の様に [...] でラインに好みの名前を付けることができます。[head-top] はヘッダエリアの上部のライン、[head-bottom] はヘッダエリアの下部のラインを、[x1]~[x4] は左から1本目~4本目のラインの名前を意味します。
.container-named-line {
display: grid;
grid:
[head-top] "head head head" 2rem [head-bottom]
[body-top] "menu main side" 2rem [body-bottom]
[foot-top] "foot foot foot" 2rem [foot-bottom]
/ [x1] 4rem [x2] 4rem [x3] 4rem [x4];
.head { grid-area: head-top / x1 / head-bottom / x4; }
.menu { grid-area: body-top / x1 / body-bottom / x2; }
.main { grid-area: body-top / x2 / body-bottom / x3; }
.side { grid-area: body-top / x3 / body-bottom / x4; }
.foot { grid-area: foot-top / x1 / foot-bottom / x4; }
}
<div class="container-named-line"> <div class="my-box head">Header</div> <div class="my-box menu">Menu</div> <div class="my-box main">Main</div> <div class="my-box side">Side</div> <div class="my-box foot">Footer</div> </div>
ギャップ(gap)
gap により、アイテム間のギャップ(隙間)を指定することができます。下記の例では、縦方向に 1rem、横方向に 4rem のギャップを指定しています。
.container-gap {
display: grid;
grid: 2rem 2rem / 3rem 3rem 3rem;
gap: 1rem 4rem;
}
<div class="container-gap"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> <div class="my-box">E</div> <div class="my-box">F</div> </div>
オートフロー(auto-flow)
高さまたは横幅に auto-flow をつけると、その後の数値を無限回繰り返すのと同じ動作になります。下記の例では、2rem 2rem / 2rem 4rem 2rem 4rem 2rem 4rem... を無限回繰り返します。auto-flow は高さか横幅かどちらか一方に指定できます。
.container-auto-flow {
display: grid;
grid: 2rem 2rem / auto-flow 2rem 4rem;
}
スパン(span)
span を指定すると N 個分のアイテムの高さ・横幅を指定することができます。
.container-span {
display: grid;
grid: auto-flow 2rem / 2rem 2rem 2rem 2rem 2rem 2rem;
}
.span-3 {
grid-column: span 3;
}
<div class="container-span"> <div class="my-box">A</div> <div class="my-box span-3">B</div> <div class="my-box">C</div> <div class="my-box">D</div> </div>
オート(auto)
auto を横幅に指定すると最大長に、高さに指定すると最低長となります。
.container-auto {
display: grid;
grid: 3rem auto 3rem / 3rem auto 3rem;
}
<div class="container-auto"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> <div class="my-box">E</div> <div class="my-box">F</div> <div class="my-box">G</div> <div class="my-box">H</div> <div class="my-box">I</div> </div>
フラクションサイズ(fr)
グリッドの長さ指定ではフラクションサイズ(fr)という単位を用いることができます。fraction は「分数」を意味します。下記では横幅の長さを、最大横幅の 1/10, 2/10, 3/10, 4/10 で指定しています。
.container-fr {
display: grid;
grid: 2rem / 1fr 2fr 3fr 4fr;
}
<div class="container-fr"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> </div>
最小最大(minmax)
minmax(min, max) は最小値と最大値を指定します。下記の例で Bアイテムは、最小でも 30rem、最大でも 40rem の横幅に制限されます。
.container-minmax {
display: grid;
grid: 2rem / 2rem minmax(30rem, 40rem) 2rem;
}
<div class="container-minmax"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> </div>
最大コンテント(max-content)
max-content は子アイテムの中で一番大きなアイテムの長さを示します。アイテムの中身がテキストの場合、アイテムの長さはテキストを改行無しで表示した場合のテキストの長さとなります。下記の例では1列目の横幅を、一番長いテキストの横幅にそろえています。
.container-max-content {
display: grid;
grid-template-columns: max-content auto;
}
<div class="container-max-content"> <div class="my-box">Short text</div> <div class="my-box">X</div> <div class="my-box">Very very long long text</div> <div class="my-box">Y</div> <div class="my-box">Middle length text</div> <div class="my-box">Y</div> </div>
最小コンテント(min-content)
min-content は、子アイテムをなるべく小さく表示します。アイテムの中身がテキストの場合は、一番長い単語の長さになります。
.container-min-content {
display: grid;
grid-template-columns: min-content auto;
}
<div class="container-min-content"> <div class="my-box">Congratulations is a long word.</div> <div class="my-box">X</div> <div class="my-box">Short text.</div> <div class="my-box">Y</div> <div class="my-box">Short text.</div> <div class="my-box">Z</div> </div>
フィットコンテント(fit-content())
fit-content(length) は基本的には length の長さとなりますが、min-content 以上 man-content 以下の範囲に制限されます。下記の例で、コンテナの横幅を広げたり狭めたりしても、左側のアイテムの横幅は、max-content(テキストを改行しない場合の横幅)より長くなることはなく、min-content(テキストを最大限改行した場合の横幅)より短くなることはありません。min-content~max-content の間は 50% となります。
.container-fit-content {
padding: .5rem;
border: 1px solid gray;
overflow: hidden;
resize: horizontal;
display: grid;
grid: 3rem / fit-content(50%) auto;
resize: both;
}
<div class="container-fit-content"> <div class="my-box">Congratulations is a long word. </div> <div class="my-box">X</div> </div>
リピート(repeat())
repeat(times, length) は length を times 回指定します。repeat(3, 10rem) は 10rem 10rem 10rem と同じ意味を持ちます。
.container-repeat {
display: grid;
grid: 2rem / 2rem repeat(3, 10rem) 2rem;
padding: .5rem;
}
<div class="container-repeat"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> <div class="my-box">E</div> </div>
times に auto-fill を指定すると length で指定した長さのアイテムをコンテナ一杯まで並べます。auto-fit は minmax(min, max) と組み合わせることで min 以上 max 以下のアイテムをコンテナの幅いっぱいに並べることができます。下記の例で枠の横幅を変更して振る舞いを確認してみてください。
.container-repeat-auto-fill {
display: grid;
grid-template-columns: repeat(auto-fill, 6rem);
padding: .5rem;
}
.container-repeat-auto-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
padding: .5rem;
}
<div class="container-repeat-auto-fill"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> <div class="my-box">E</div> </div> <div class="container-repeat-auto-fit"> <div class="my-box">A</div> <div class="my-box">B</div> <div class="my-box">C</div> <div class="my-box">D</div> <div class="my-box">E</div> </div>
密集(dense)
dense は「密集」という意味を持ちます。大きさの異なるアイテムを詰めていく際、通常であれば直前のアイテムの次の位置に詰めますが、dense を指定すると空きスペースがあればそこに埋めます。
.container-no-dense {
display: grid;
grid: 2rem 2rem 2rem 2rem / 2rem 2rem 2rem;
}
.container-dense {
display: grid;
grid: auto-flow 2rem 2rem 2rem 2rem / 2rem 2rem 2rem;
grid-auto-flow: dense;
}
.big {
grid-row: span 2; grid-column: span 2;
}
<b>no dense</b> <div class="container-no-dense"> <div class="my-box grid-item">A</div> <div class="my-box grid-item big">B</div> <div class="my-box grid-item big">C</div> <div class="my-box grid-item">D</div> </div> <b>dense</b> <div class="container-dense"> <div class="my-box grid-item">A</div> <div class="my-box grid-item big">B</div> <div class="my-box grid-item big">C</div> <div class="my-box grid-item">D</div> </div>
サブグリッド(subgrid)
2023年9月の Chrome 117 がリリースされ、主要モダンブラウザでサブグリッド(subgrid)がサポートされました。下記の例ではコンテナの中にアイテムとしてカード(card)を表示しています。さらに、カードをサブグリッドとして扱い、カード内のタイトルなどの子要素をサブアイテムとして扱っています。これにより、各カード間のタイトルの高さをそろえたりすることが可能となります。下記の例で 「subgrid指定」のチェックボックスを On/Off して、サブグリッド指定時と未指定時の振る舞いを確認してください。
.container-subgrid {
display: grid;
grid-template-columns: repeat(auto-fit, 10rem);
gap: .5rem 2rem;
padding: .5rem;
}
.card {
display: grid;
grid-template-rows: subgrid;
border: 1px solid #999;
grid-row: span 2;
padding: .5rem;
}
.card-title {
font-weight: bold;
font-size: 120%;
}
.card-pict {
height: 5rem;
text-align: center;
border: 1px solid #999;
}
<div class="container-subgrid">
<div class="card">
<div class="card-title">Short Title</div>
<div class="card-pict">Picture</div>
</div>
<div class="card">
<div class="card-title">Long Long Long Title</div>
<div class="card-pict">Picture</div>
</div>
<div class="card">
<div class="card-title">Very Very Very Very Long Long Long Long Long Title</div>
<div class="card-pict">Picture</div>
</div>
</div>
グリッドレイアウト
グリッドのレイアウトを指定するものに下記があります。詳細は 「フレックス・グリッドのレイアウト」を参照してください。
.container-layout {
display: grid;
grid: 2rem / auto-flow 10rem;
margin-bottom: 1rem;
border: 1px solid #ccc;
background-color: #eee;
}
.cjc-left { justify-content: left; }
.cjc-center { justify-content: center; }
.cjc-right { justify-content: right; }
.cjc-space-between { justify-content: space-between; }
.cjc-space-around { justify-content: space-around; }
.cjc-space-evenly { justify-content: space-evenly; }
<div class="container-layout cjc-xxxx"> <div class="my-box">xxxx</div> <div class="my-box">xxxx</div> <div class="my-box">xxxx</div> </div>
CSSプロパティ
親コンテナに指定するプロパティには下記があります。
- display: grid
- この要素がグリッドのコンテナであることを示します。
- grid: ...
- grid-template, grid-template-row, grid-template-columns, grid-auto-row, grid-auto-columns をまとめて指定します。
- grid-template: ...
- grid-template-rows, grid-template-columns をまとめて指定します。
- grid-template-arias: ...
- エリア名を定義します。
- grid-template-rows, grid-template-columns: ...
- アイテムの高さ、横幅、線名を指定します。
- grid-auto-flow: ...
- アイテムを並べる方向、および、アイテムの密集度を指定します。
- grid-auto-rows, grid-auto-columns: ...
- アイテムのデフォルトの高さ、横幅を指定します。
子アイテムに指定するプロパティには下記があります。
- grid-area: ...
- 子アイテムに指定して、grid-row, grid-column をまとめて指定します。
- grid-row: ...
- 子アイテムに指定して、grid-row-start, grid-row-end をまとめて指定します。
- grid-column: ...
- 子アイテムに指定して、grid-column-start, grid-column-end をまとめて指定します。
- grid-row-start, grid-row-end, grid-column-start, grid-column-end: ...
- 子アイテムに指定して、縦方向の開始ライン、横方向の開始ライン、縦方向の終了ライン、横方向の終了ラインを、ライン番号またはライン名で指定します。
文法
grid:
<grid-template>
| <grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>?
| [ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>
grid-template:
none
| [ <grid-template-rows> / <grid-template-columns> ]
| [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?
grid-template-areas:
none
| <string>+
grid-template-rows, grid-template-columns:
none
| <track-list>
| <auto-track-list>
| subgrid <line-name-list>?
grid-auto-flow:
[ row | column ] || dense
grid-auto-rows, grid-auto-columns:
<track-size>+
grid-aria:
<grid-line> [ / <grid-line> ]{0,3}
grid-row, grid-column:
<grid-line> [ / <grid-line> ]?
grid-row-start, grid-column-start, grid-row-end, grid-column-end:
<grid-line>
<track-list> = [ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>?
<auto-track-list> = [ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>? <auto-repeat>
[ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>?
<explicit-track-list> = [ <line-names>? <track-size> ]+ <line-names>?
<line-name-list> = [ <line-names> | <name-repeat> ]+
<track-size> = <track-breadth>
| minmax( <inflexible-breadth> , <track-breadth> )
| fit-content( <length-percentage [0,∞]> )
<fixed-size> = <fixed-breadth>
| minmax( <fixed-breadth> , <track-breadth> )
| minmax( <inflexible-breadth> , <fixed-breadth> )
<grid-line> = auto
| <custom-ident>
| [ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ]
| [ span && [ <integer [1,∞]> || <custom-ident> ] ]
<track-breadth> = <length-percentage [0,∞]> | <flex [0,∞]> | min-content | max-content | auto
<inflexible-breadth> = <length-percentage [0,∞]> | min-content | max-content | auto
<fixed-breadth> = <length-percentage [0,∞]>
<line-names> = '[' <custom-ident>* ']'
<track-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <track-size> ]+ <line-names>? )
<auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
<fixed-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
<name-repeat> = repeat( [ <integer [1,∞]> | auto-fill ], <line-names>+ )
リンク
- grid (MDN)
- grid-template (MDN)
- grid-template-areas (MDN)
- grid-template-rows (MDN)
- grid-template-columns (MDN)
- grid-auto-flow (MDN)
- grid-auto-row (MDN)
- grid-auto-column (MDN)
- grid-aria (MDN)
- grid-row (MDN)
- grid-column (MDN)
- grid-row-start (MDN)
- grid-row-end (MDN)
- grid-column-start (MDN)
- grid-column-end (MDN)