模写修行メディア

【CSS Grid入門】図解も交えて使い方を詳しく解説!

CSS Gridは、レイアウトを作るときに便利な機能です。

普段Flexboxを使ってレイアウトを作っている方も多いのではないでしょうか。CSS Gridを使えばFlexboxよりもよりスッキリかける場合もあるので、知っておくととても便利です。

この記事ではCSS Gridについて、図解も交えて詳しく解説します。

自動配置アルゴリズムに関しては深く触れません。いつか別記事として書きたいと思います。

CSS Grid とは?

CSS Gridとは?

CSS Gridとはレイアウトを作るときに便利な機能(仕様)です。CSS Gridを使うと上の画像のように行と列で区切ったグリッドの中にコンテンツを自由に配置する事ができます。

CSS GridとFlexboxは何が違う?

CSS GridとFlexboxと何が違う?

Flexboxは1次元レイアウトで、CSS Gridは2次元レイアウトになります。

上の画像はどちらも2 × 2のグリッドの中にコンテンツが入っているように見えますが、実際のところは横に並んでいる要素の3番目が折り返していると捉えるのが正確です。それに対して、CSS Gridは行と列がある2次元で、あらかじめ決めておいた領域に対してコンテンツをはめていると解釈するとイメージがつきやすいです。

この1次元か2次元かの考え方は、CSS GridとFlexboxのどちらを使えば良いか迷った時の判断にも役に立ちます。(いつかそのテーマで記事を書きたいと思います)

CSS 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つの場合も)をエリアと呼びます。

エリアを自由に定義して、そこにアイテムを配置する事ができます。

CSS Gridを簡単な例で試してみよう!

簡単なレイアウトを作りながら、使い方を紹介します。

  • コンテナ側に指定するプロパティ
  • アイテム側に指定するプロパティ

Flexboxと同様に上の2つに分類することができます。

簡単なグリッドレイアウトの例

まずはこのようなレイアウトを作ってみます。

注意
これ以降に紹介するコードは背景色やpaddingなど、CSS Gridを紹介する上で重要でないコードは省略しています。
<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-rowgrid-columnの指定がない場合、上の画像のように左上から順に配置されます。

トラックのサイズ指定に使える単位

grid-template-rowsgrid-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を使う

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を使う

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を指定したトラックはコンテンツによってサイズが自動で決まります。

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で配分しています。

知っておくとGood
後述するauto-fitとminmaxを利用すると、メディアクエリなしで、幅によってカラム数を切り替えることが出来ます。

エリアを指定してグリッドを作る

エリアを指定してグリッドを作る例
<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-areasgrid-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-rowsgrid-auto-columnsを使うことで、暗黙的なグリッドのトラックのサイズを指定できます。

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

上の画像のように、grid-auto-rowsgrid-auto-columnsは明示していない行や列に対して効きます。

.container {
    ...
    grid-auto-rows: minmax(100px, auto);
}

このように指定することで、最低でも100pxは担保しつつ、100pxを超える量のコンテンツが入る場合はコンテンツに応じて自動でサイズが決まるようにも出来ます。

gapでアイテム間の余白を作る

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-columngrid-rowで配置場所を指定している場合、その指定が優先されます。

auto-fillとauto-fit

repeatを使って繰り返し回数にauto-fill / auto-fitを指定した場合の挙動を紹介します。

auto-fillを指定した場合

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-fillを指定した場合の例

今回の例で考えると、画面幅を狭めると上の画像のような配置になります。

auto-fitを指定した場合

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-fillauto-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-fitminmaxを利用すると、メディアクエリなしでカラム数を切り替えることが出来ます。動画は上が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-contentとalign-contentの例

図で見たほうが分かりやすいと思うので、いくつかのパターンを用意しました。

justify-items と align-items

justify-itemsは主軸方向、align-itemsはクロス軸方向のセル内での位置を指定できます。コンテナに対して指定するプロパティです。

  • start
  • center
  • end
  • stretch

主な取れる値です。

justify-itemsとalign-itemsの例

こちらもいくつかのパターンを用意しました。

justify-selfとalign-self

アイテムに対して指定するプロパティです。justify-itemsやとalign-itemsは全てのアイテムに適応されましたが、justify-selfalign-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 を使って重なり順を指定

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を指定することで上にすることが出来ます。

ショートバンドと自動配置アルゴリズムに関して

紹介したプロパティの中にはショートバンドが用意されているものもあります。ショートバンドは記述が少なくなる一方で、可読性は下がるので個人的に使っていません。興味がある方は調べてみてください。

また、冒頭の注意にも書いた通り、自動配置アルゴリズムに関しては深く触れませんでした。

コーディングの練習が出来るサービスを作りました 🎉

模写修行はこんな方におすすめ!

  • プロの制作フローを学びたい
  • どんなことを考えながら書くのか知りたい
  • 実践的な練習がしたい

【初級編】はこんな方におすすめ!

  • 基礎学習中、もしくは終えたばかり
  • サイト制作経験が5サイト未満 (実際の案件でなくてもOK)

【中級編】はこんな方におすすめ!

  • CSS設計を意識したコーディングを学びたい
  • SCSSを使った書き方を学びたい (解説はSCSSを使わない前提でします)

模写修行ではデザインデータ(XD) / web上で見れる解説 / サンプルコードを配布しています。ご自身でデザインを見ながらコーディングに挑戦し、解説とサンプルコードで深く学ぶことができるサービスです。

模写修行を見る

この記事を書いた人

Gakuのアイコン

Gaku / @gaku92014091

大学・大学院時代から個人で仕事をする。卒業後5年間のフリーランス期を経て、法人化。マーケティング、デザイン、コーディング、プログラミング(フロント)、幅広くやります。webサービス作るのが好き!

\Share/

模写修行のトップページのスクリーンショット
模写修行

駆け出しエンジニアのためのコーディング練習教材