CSS Gridは、レイアウトを作るときに便利な機能です。
普段Flexboxを使ってレイアウトを作っている方も多いのではないでしょうか。CSS Gridを使えばFlexboxよりもよりスッキリかける場合もあるので、知っておくととても便利です。
この記事ではCSS Gridについて、図解も交えて詳しく解説します。
自動配置アルゴリズムに関しては深く触れません。
👇 メンターやってます 👇
模写修行やこのメディアを作ったエンジニア中心に、メンタリングサービスHello Mentorを運営しています。
- 独学に限界を感じている...
- 何をどこまで勉強すれば良いかわからない...
- 自分の書き方が正しいかわからない...
- 検索しても解決しない問題が多い...
- 転職や副業のアドバイスが欲しい...
このような方は、ぜひ下記のリンクからサービス詳細をご覧ください。個別説明会もお気軽にお申し込みください。
👆 メンターやってます 👆
この記事の目次
CSS Gridとは?
CSS Gridとはレイアウトを作るときに便利な機能(仕様)です。CSS Gridを使うと上の画像のように行と列で区切ったグリッドの中にコンテンツを自由に配置する事ができます。
CSS GridとFlexboxは何が違う?
Flexboxは1次元レイアウトで、CSS Gridは2次元レイアウトになります。
上の画像はどちらも2 × 2のグリッドの中にコンテンツが入っているように見えますが、Flexboxのほうは横に並んでいる要素の3番目が折り返していると捉えるのが正確です。それに対して、CSS Gridは行と列がある2次元で、あらかじめ決めておいた領域に対してコンテンツをはめていると解釈するとイメージがつきやすいです。
この1次元か2次元かの考え方は、CSS GridとFlexboxのどちらを使えば良いか迷った時の判断にも役に立ちます。
Flexboxの使い方をどこよりも詳しく解説!図解やサンプルもあり!Flexboxの使い方に関しては、上の記事で詳しく紹介しています。
CSS Gridを理解するための基本概念
CSS Gridを理解するためにまずは基本概念を紹介します。ここで紹介する用語はこれ以降たくさん出てくるので、必ず抑えておきましょう。
コンテナとアイテム
Flexbox同様に、CSS Gridもコンテナの中にアイテムがあります。
<div class="container">
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
</div>
.container{
display: grid;
/* or */
display: inline-grid;
...
}
このようにコンテナの直下にアイテムを配置します。そして、コンテナに対して、display: grid;
もしくはdisplay: inline-grid;
を指定します。
ライン
グリッドを分ける垂直と水平の線をラインと呼びます。
1番目から最後のラインまで番号が振られていて、その番号を使って領域を指定することになります。
また、番号は左から右、上から下へ向かって、1,2,3,...となっていますが、逆からの番号もマイナスを使って振られています。つまり上の画像の例だと、『4番目(= -1番目)、3番目(= -2番目)、...』のようになっています。
トラック
行と列のことをトラックと呼びます。
トラックのサイズを指定して、グリッドを定義します。
セル
ラインで区切られた領域をセルと呼びます。
セルに対してアイテムを配置します。
エリア
セルの塊(1つの場合も)をエリアと呼びます。
エリアを自由に定義して、そこにアイテムを配置する事ができます。
【駆け出しの方へ】独学に限界を感じてませんか?
プログラミングやデザインは独学可能ですが、ほとんんどの方が苦戦します。
↓このように感じていませんか?
- 何をどこまで勉強すれば良いかわからない...
- 自分の書き方が正しいかわからない...
- 検索しても解決しない問題が多い...
- 転職や副業するまでの道が見えない...
そんな問題を解決するために、模写修行やこのメディアを作ったエンジニア/デザイナー中心に、メンタリングサービスHello Mentorを始めました。
スクールのような大金は必要ありません。高額な費用は払いたくないけど、プロのサポートが欲しい方は、ぜひ下記のリンクからサービス詳細をご覧ください。
👆 メンターは全員現役エンジニア 👆
CSS Gridを簡単な例で試してみよう!
簡単なレイアウトを作りながら、使い方を紹介します。
- コンテナ側に指定するプロパティ
- アイテム側に指定するプロパティ
Flexboxと同様に上の2つに分類することができます。
まずはこのようなレイアウトを作ってみます。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px;
}
.item:nth-child(1) {
grid-column: 1 / 2;
grid-row: 1 / 2;
...
}
.item:nth-child(2) {
grid-column: 2 / 4;
grid-row: 1 / 2;
...
}
.item:nth-child(3) {
grid-column: 1 / 3;
grid-row: 2 / 3;
...
}
.item:nth-child(4) {
grid-column: 3 / 4;
grid-row: 2 / 3;
...
}
全体のコードはこのようになります。コンテナとアイテムのコードを詳しく紹介します。
コンテナ側の指定
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px;
}
プロパティ | 役割 |
---|---|
grid-template-rows | 行の各トラックの高さを指定 |
grid-template-columns | 列の各トラックの幅を指定 |
- 2 行 3列のトラック
- 100px × 100pxのセル
上の条件のグリッドができたことになります。あとはそのグリッドに対して、各アイテムを配置する指定すればOKです。
.container {
...
/* 👇 grid-template-columns: 100px 100px 100px;と同じこと */
grid-template-columns: repeat(3, 100px);
}
.container02 {
...
/* 👇 grid-template-columns: 100px 100px 100px 200px;と同じこと */
grid-template-columns: repeat(3, 100px) 200px;
}
数値が同じ場合は、上のようにrepeatを使うことも出来ます。
アイテム側の指定
.item:nth-child(1) {
grid-row: 1 / 2;
grid-column: 1 / 2;
...
}
.item:nth-child(2) {
grid-row: 1 / 2;
grid-column: 2 / 4;
...
}
.item:nth-child(3) {
grid-row: 2 / 3;
grid-column: 1 / 3;
...
}
.item:nth-child(4) {
grid-row: 2 / 3;
grid-column: 3 / 4;
...
}
プロパティ | 役割 |
---|---|
grid-row | アイテムを配置する行の番号を指定 |
grid-column | アイテムを配置する列の番号を指定 |
.item:nth-child(1)
を例にすると、grid-row: 1 / 2;
と指定することで、1 番目のライン(row)と 2 番目のライン(row)の間のトラック(row)を指定しています。そして、grid-column: 1 / 2;
で 1 番目のライン(column)と 2 番目のライン(column)の間のトラック(column)を指定しています。この重なり合った部分が、.item:nth-child(1)
の配置場所です。
図にするとこのようになります。1 / 2 は『1番目のライン ~ 2番目のライン』と頭の中で変換するとわかりやすいです。
/* 隣り合うラインを指定する場合、省略して書ける */
.item {
...
/* 👇 grid-row: 1 / 2;と同じこと */
grid-row: 1;
/* 👇 grid-column: 2 / 3;と同じこと */
grid-column: 2;
}
/* spanを使って何個先のラインまでかを指定することが出来る */
.item {
...
/* 👇 grid-row: 1 / 3;と同じこと */
grid-row: 1 span 2;
/* 👇 grid-column: 2 / 4;と同じこと */
grid-column: 2 span 2;
}
/* マイナスを使って逆から何番目か指定することが出来る */
.item {
...
/* コンテナに grid-template-columns: repeat(3, 100px); があると仮定 */
/* 👇 grid-column: 1 / 3;と同じこと */
grid-column: -4 / -2;
}
- 隣り合うラインを指定する場合、省略して書ける
- span を使って何個先のラインまでかを指定することが出来る
- マイナスを使って逆から何番目か指定することが出来る
これらの書き方も可能です。
仮にアイテム側で、grid-row
やgrid-column
の指定がない場合、上の画像のように左上から順に配置されます。
トラックのサイズ指定に使える単位
grid-template-rows
やgrid-template-columns
ではpx以外にも、幅や高さで使う単位が使えます。特に使用頻度が多い、 % / fr / auto / minmaxについて紹介します。
%を使う
<div class="container">
<div class="item">main</div>
<div class="item">side</div>
</div>
.container {
display: grid;
grid-template-columns: 80% 20%;
}
このように%を使うことも出来ます。行(row)に対する指定を省略しているので、高さはコンテンツの量によって自動で決まります。
frを使う
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.container {
width: 400px;
display: grid;
grid-template-columns: 100px 1fr 2fr;
}
frは余ったスペースを指定した比率で埋めます。
上の例では、コンテナを400pxにしているので、100pxを埋めたあとの残りの300pxを1:2で配分するので、100px 100px 200px
と指定したときと同じになります。
frだけを使って、grid-template-columns: 1fr 1fr 2fr;
のような指定もできます。
autoを使う
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.container {
width: 400px;
display: grid;
grid-template-columns: 1fr 1fr auto;
}
autoを指定したトラックはコンテンツによってサイズが自動で決まります。
同じ指定でもコンテンツが違うと、トラックのサイズも変わります。
frとautoの違いは紛らわしいかもしれませんが、**『frは余ったスペースの分配、autoはコンテンツによって自動でサイズが決まる』**ということを意識しておくと良いです。
minmaxを使う
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.container {
display: grid;
grid-template-columns: minmax(200px, 1fr) 1fr 1fr;
}
minmaxではトラックの最小と最大のサイズを指定する事ができます。いくつかの具体的な数値でみるとイメージがつきやすいです。
👇 container
が900pxのとき
アイテム | アイテムの幅 |
---|---|
item:nth-child(1) | 300px |
item:nth-child(2) | 300px |
item:nth-child(3) | 300px |
👇 container
が600pxのとき
アイテム | アイテムの幅 |
---|---|
item:nth-child(1) | 200px |
item:nth-child(2) | 200px |
item:nth-child(3) | 200px |
👇 container
が400pxのとき
アイテム | アイテムの幅 |
---|---|
item:nth-child(1) | 200px |
item:nth-child(2) | 100px |
item:nth-child(3) | 100px |
item:nth-child(1)
の最小が200pxなので、それより小さくなることはありません。item:nth-child(1)
が200px確保して、余った200pxを 1:1で配分しています。
エリアを指定してグリッドを作る
<div class="container">
<header class="header">header</header>
<main class="main">main</main>
<aside class="side">side</aside>
<footer class="footer">footer</footer>
</div>
.container {
display: grid;
grid-template-columns: 70% 30%;
grid-template-areas:
"header header"
"main side"
"footer footer";
}
.header {
grid-area: header;
...
}
.main {
grid-area: main;
...
}
.side {
grid-area: side;
...
}
.footer {
grid-area: footer;
...
}
grid-template-areas
とgrid-area
を使ってエリアを定義することも出来ます。
暗黙的なグリッド
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
上のコードのようにgrid-template-columns
だけの指定でも、アイテムが2個より多い場合にも2行目のトラックが自動で作られ、そこにitem:nth-child(3)
が配置されました。これを暗黙的なグリッドと呼びます。
- grid-template-rows
- grid-template-columns
- grid-template-areas
上のプロパティで定義して作ったグリッドは明示的なグリッドと呼びます。
暗黙的なグリッドのサイズ指定
.container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: 100px;
}
grid-auto-rows
やgrid-auto-columns
を使うことで、暗黙的なグリッドのトラックのサイズを指定できます。
上の画像のように、grid-auto-rows
やgrid-auto-columns
は明示していない行や列に対して効きます。
.container {
...
grid-auto-rows: minmax(100px, auto);
}
このように指定することで、最低でも100pxは担保しつつ、100pxを超える量のコンテンツが入る場合はコンテンツに応じて自動でサイズが決まるようにも出来ます。
gapでアイテム間の余白を作る
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(2, 100px);
grid-template-rows: repeat(2, 100px);
gap: 10px;
}
gapを使うとアイテム間の余白を作る事ができます。余白が入るのは"アイテム間"だけなので、1番上や下、1番左や右には余白が入らないのがポイントです。nth-child
やネガティブマージンを使う必要がないのはとても便利です。
gap: 20px 10px;
のように指定することで、上方向の余白(行間の余白)と下方向の余白(列間の余白)を別々に指定することもできます。
orderで順番を変更
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
}
.item:nth-child(1) {
order: 2;
...
}
.item:nth-child(2) {
order: 3;
...
}
.item:nth-child(3) {
order: 1;
...
}
このようにorder
で自由に順番を変更することが出来ます。ただし、grid-column
やgrid-row
で配置場所を指定している場合、その指定が優先されます。
auto-fillとauto-fit
repeat
を使って繰り返し回数にauto-fill
/ auto-fit
を指定した場合の挙動を紹介します。
auto-fillを指定した場合
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
}
repeat
を使って繰り返し回数にauto-fill
を指定すると、コンテナの幅に入るだけのアイテムが入り、入りきらなかったものは次の行に配置されます。
auto-fill
を指定した場合、余った部分には十分にスペースがあれば空のセルが入ります。
今回の例で考えると、画面幅を狭めると上の画像のような配置になります。
auto-fitを指定した場合
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
}
auto-fill
との違いは、**余った部分には空のセルが入らないことです。**今回の例だと、auto-fill
でもauto-fit
でも全コンテナ幅で全く同じ見た目になります。
auto-fill
とauto-fit
で違いが出るケースを次に紹介します。
メディアクエリなしでカラム数を切り替える
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* or */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
auto-fill
/ auto-fit
とminmax
を利用すると、メディアクエリなしでカラム数を切り替えることが出来ます。動画は上がauto-fill
を指定した場合、下がauto-fit
を指定した場合です。
前述した通り、auto-fill
は空のセルが入るので、幅を広げていくと目には見えませんが、どんどん空のセルが追加されています。
auto-fit
は空のセルが入らないので、コンテナの幅が800pxを超えてもコンテナ幅に全アイテム均等幅で入ります。
コンテナやアイテムの配置
コンテナやアイテムの配置が指定できるプロパティを紹介します。Flexboxを学習済みの方はすんなり理解できると思います。
justify-content と align-content
justify-content
は主軸方向、align-content
はクロス軸方向のセルの位置を指定できます。コンテナに対して指定するプロパティです。
- start
- center
- end
- space-between
- space-around
- space-evenly
主な取れる値です。
図で見たほうが分かりやすいと思うので、いくつかのパターンを用意しました。
justify-items と align-items
justify-items
は主軸方向、align-items
はクロス軸方向のセル内での位置を指定できます。コンテナに対して指定するプロパティです。
- start
- center
- end
- stretch
主な取れる値です。
こちらもいくつかのパターンを用意しました。
justify-selfとalign-self
アイテムに対して指定するプロパティです。justify-items
やとalign-items
は全てのアイテムに適応されましたが、justify-self
とalign-self
は各アイテムに対して個別に指定するプロパティです。
取れる値は、justify-items
やとalign-items
と同じです。
- start
- center
- end
- stretch
主な取れる値です。
上下左右で中央に配置
<div class="container">
<div class="item">center</div>
</div>
.container {
display: grid;
place-items: center;
}
place-items: center;
を使うと、2行で上下中央配置ができます。
z-index を使って重なり順を指定
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(2, 100px);
grid-template-rows: repeat(2, 100px);
}
.item:nth-child(1) {
grid-row: 1 / 2;
grid-column: 1 / 3;
z-index: 1;
...
}
.item:nth-child(2) {
grid-row: 1 / 2;
grid-column: 2 / 3;
...
}
.item:nth-child(3) {
grid-row: 2 / 3;
grid-column: 1 / 2;
...
}
.item:nth-child(4) {
grid-row: 2 / 3;
grid-column: 2 / 3;
...
}
.item:nth-child(1)
にz-index
を指定しています。
指定しない場合、画像の通りHTMLで先に書いてある.item:nth-child(1)
が、.item:nth-child(2)
より下になります。z-index
を指定することで上にすることが出来ます。
ショートバンドと自動配置アルゴリズムに関して
紹介したプロパティの中にはショートバンドが用意されているものもあります。ショートバンドは記述が少なくなる一方で、可読性は下がるので個人的に使っていません。興味がある方は調べてみてください。
また、冒頭の注意にも書いた通り、自動配置アルゴリズムに関しては深く触れませんでした。
独学に限界を感じていませんか?
模写修行やこのメディアを作ったエンジニア中心に、メンタリングサービスHello Mentorを運営しています。
👇 こんな方のためのサービスです。
- 独学に限界を感じている...
- 何をどこまで勉強すれば良いかわからない...
- 自分の書き方が正しいかわからない...
- 検索しても解決しない問題が多い...
- 転職や副業のアドバイスが欲しい...
メンターを務めるのは、今も現役でコードを書いているエンジニアのみです。駆け出しの方やメンターだけをやっている方はいません。
高額な料金はかかりません。サブスク&入会金・解約料なしなので、リスクなく始められます。
少しでも興味がある方は、ぜひ下記のリンクからサービスサイトをご覧ください。個別説明会もお気軽にお越しください。(無理な営業等一切ございません!)
当メディア運営メンバーでメンターやってます!👉
詳しく見る
0からweb制作やプログラミングの勉強を始める方はもちろん、12ヶ月以上独学している方や既にお仕事をしている方にもご利用いただいています!