イケてるしヤバいプロパティ「CSS Grid」でイケてるレイアウトを作ろう

本日は将来使えるレイアウト、CSS Gridを紹介します。

目次

CSS Gridとは

ボックスの表示を制御するプロパティです。

縦と横の軸を指定して表示できるため、レイアウトの為に無駄に入れ子する必要がなくなります。

レイアウトのためのプロパティは他にもFloatとFlexBoxがありますが、これらは縦または横のどちらか1列しか自由に配置できません。

つまりどういう事?

  • その名の通りグリッド状にレイアウトしたい時
  • 高さや幅が異なる要素をタイル状に並べたい時
  • 要素を縦横自由に配置したい時

等に真価を発揮します。

使い方

親要素に「display:grid」または「display:inline-grid」を指定すると、親要素は「グリッドコンテナー」になります。

ここで任意のサイズのグリッドトラックを作成します。

するとグリッドコンテナーにグリッドラインという線が引かれます。

親要素に包まれている子要素は「グリッドアイテム」になり、引かれたグリッドラインに沿って自由に配置ができるようになります。

実際にやってみよう

CSS Gridの基本的なプロパティを使って、以下のようなデザインを作ってみます。

ブラウザ上の表示

HTMLを書く

まずグリッドレイアウトを表示するためのHTMLを書いていきます。

親要素を作り、その直下に要素を作ります。今回は6つの要素が必要なので、直下に6つ作ります。

<div class="parent">
  <div class="child1">1</div>
  <div class="child2">2</div>
  <div class="child3">3</div>
  <div class="child4">4</div>
  <div class="child5">5</div>
  <div class="child6">6</div>
</div>

HTMLは何とこれだけで済みます。余分にコンテナを作成する必要がありません。感動。

グリッドコンテナーを作る

続いてCSSを書いていきましょう。

今回は全体の高さが490px、幅は自動のレイアウトを作成します。

まずは親要素にdisplay:gridを指定します。

.parent{
  display:grid;
  height:490px;
}

これで親要素(このHTMLでいうと.parent)がグリッドアイテムを囲む箱であるグリッドコンテナーになりました。

同時に、子要素(.child1~6)はグリッドアイテムになり、これから引くグリッドラインに沿って自由に配置できるアイテムになります。

グリッドトラックを作る

上の例の通りのレイアウトにしたいので、グリッドコンテナー内に、縦方向に4つ、横方向に3つ分割した状態のグリッドトラックを作成します。

グリッドトラックは、グリッドの1行、または1列をさす言葉です。

グリッドトラックの作成には以下のプロパティを使います。

  • grid-template-columns
  • grid-template-rows

まずgrid-template-columnsプロパティで、グリッドを縦に分割します。

分割したい数だけ値を記入します。値の間はスペースをあけて入力します。

カラムの1列ごとのサイズも、ここで指定します。

.parent{
  display:grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  height:490px;
}

今回は「fr」(fraction/比率)という単位でサイズを指定し分割しました。
幅や高さを相対的に指定できるすごいやつです。

例えば「grid-template-columns」に「2fr 1fr 1fr」を指定すると、2frのカラムは50%、1frのカラムは25%の幅で3分割されます。

この状態ではブラウザ上には何も表示されませんが、こんな風になっています。

グリッドコンテナー上に5本の縦線が引かれ、均等な幅で4つに分割されています。

グリッドコンテナーを分割しグリッドトラックを作ると、トラックとトラックの間に見えない線が引かれます。

これを「グリッドライン」と言います。

横はgrid-template-rowsプロパティを使って分割します。
(書き方、使える値はgrid-template-columnsプロパティと同じです)

.parent{
  display:grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  height:490px;
}

グリッドラインが縦に5本、横に4本引かれ、コンテナーがそれぞれ均等なサイズで縦4つ、横3つに分割されました。

以上の記述はgrid-templateプロパティで一括に指定する事もできます。

.parent{
  display:grid;
  /* row(行)、column(列)の順で指定します
     rowとcolumnの値の間には、スラッシュを入力します */
  grid-template: 1fr 1fr 1fr / 1fr 1fr 1fr 1fr;
  height:490px;
}

グリッドアイテムを配置する


グリッドアイテムは、指定したグリッドラインに沿って配置します。

グリッドアイテムの配置には以下のプロパティを使います。

  • grid-row-start
  • grid-row-end
  • grid-column-start
  • grid-column-end

grid-row-○○はグリッドアイテムの行(横)、grid-column-○○はグリッドアイテムの列(縦)の配置を指定します。

今回の場合、1番目の子要素(.child1)は1番目の列と1番目の行に配置して、3番目の列と3番目の行まで表示したいので、こう書きます。

.child1{
  grid-row-start: 1;
  grid-row-end: 3;
  grid-column-start: 1;
  grid-column-end: 3;
}

ショートハンドを使って入力する事もできます。

grid-rowはグリッドアイテムの行(横)、grid-columnはグリッドアイテムの列(縦)の配置を一括で指定できます。

ショートハンドを使う場合は、グリッドの配置を開始する位置を左に、グリッドの配置を終了する位置を右に書きます。

.child1{
  grid-row: 1/3;
  grid-column: 1/3;
}

行グリッド、列グリッドの開始位置・終了位置を全てまとめて指定したい場合は、「grid-area」プロパティを使用します。

.child1{
  /* 左から、
  grid-row-start / grid-column-start / grid-row-end / grid-column-end
  の値 */
  grid-area: 1 / 1 / 3 / 3;
}

こんな感じで配置しました。

.child1{
  grid-row: 1/3;
  grid-column: 1/3;
}
.child2{
  grid-row: 3/4;
  grid-column: 1/2;
}
.child3{
  grid-row: 3/4;
  grid-column: 2/3;
}
.child4{
  grid-row: 1/2;
  grid-column: 3/4;
}
.child5{
  grid-row: 1/2;
  grid-column: 4/5;
}
.child6{
  grid-row: 2/4;
  grid-column: 3/5;
}

行と列を一括で指定するgrid-rowとgrid-columnで書きました。

start~endまでプロパティを全部使うと煩雑すぎ、grid-areaで全部ショートハンドにするとややこしい(個人的に)ので、こう書いています。

ブラウザ上の表示はこうなります。
(わかりやすくなるよう色分けしています)

よりわかりやすくすると、こんな感じです。

グリッド間の隙間を指定する

配置はできましたが、アイテムの間に隙間がなく詰まって見えます。

  • column-gap
  • row-gap

上記のプロパティを追加して、隙間をあけます。

column-gapで列(縦)、row-gapで行(横)の隙間を指定します。

.parent{
  display:grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  height:490px;
  /* 追加 */
  column-gap: 12px;
  row-gap: 12px;
}

表示はこんな感じ

↓よりわかりやすく

従来のFloatやFlexBoxですと、隣接する子要素の間に隙間をあけたい時には、子要素ごとに余白をつける必要がありました。

Gridは親要素にgapプロパティを付ければ、子要素に自動的に隙間をあけてくれます。

隙間ができるのはグリッドアイテムの間だけなので、グリッドコンテナーの四辺に余白はつきません。

隙間の幅はショートハンドで記述する事もできます。

一括で指定したい場合、grid-gapプロパティを使います。

.parent{
  /* row(行)、column(列)の順で指定します */
  grid-gap: 12px 12px;
  /* どちらも同じ値の場合、省略もできます */
  grid-gap: 12px;
}

完成


これで完成です。かなりシンプルな工程で済みますよね!

たとえば同じ事をやりたい時、たとえばFlexBoxだと以下のような工程になります。

HTML

<div class="container">
  <div class="parent1">
    <div class="parent1-child1">1</div>
    <div class="parent1-child2">2</div>
    <div class="parent1-child3">3</div>
  </div>
  <div class="parent2">
    <div class="parent2-child1">4</div>
    <div class="parent2-child2">5</div>
    <div class="parent2-child3">6</div>
  </div>
</div>

CSS

.container{
  display: flex;
}

.parent1, .parent2 {
  display: flex;
  flex-wrap: wrap;
  width: 50%;
}

.parent2{
  margin: 0 0 0 12px;
}

.parent1-child1{
  width: 100%;
}

.parent1-child1, .parent2-child3{
  height: calc(((490px - 12px) / 3) * 2);
}

.parent1-child2, .parent1-child3, .parent2-child1, .parent2-child2 {
  height: calc((490px - 12px) / 3);
}

.parent1-child2, .parent1-child3{
  width: calc(50% - 6px);
}

.parent1-child2{
  margin: 12px 0 0;
}

.parent1-child3 {
  margin: 12px 0 0 12px;
}

.parent2-child1, .parent2-child2 {
  width: calc(50% - 6px);
}

.parent2-child2 {
  margin: 0 0 0 12px;
}

.parent2-child3 {
  margin: 12px 0 0 0;
  width: 100%;
}

図解

こんな感じで、

  • 親要素を2つ作り子要素を3つずつくるんで、親要素にFlexBoxを適用し、さらに上からコンテナーでくるみ、それにもFlexBoxを適用して親要素を横並びに…と書かないとといけない
  • さらに、 要素間に隙間を開けたかったり、最初の例のように子要素の大きさを変えながら配置したければ、さらに子要素に記述を足さないといけない

ので、書くのが面倒なうえ読みづらいコードになりますが、CSS Gridなら上記で示した通り、だいぶキレイに書けます!

いかがでしたか?
CSS Gridを知らない方に向けて書いてみましたが、私自身まだまだ理解が浅く、もっと効率の良い書き方があるかもしれません。

今回説明したプロパティはごく一部です。

CSS gridにはこの他にもたくさん便利なプロパティがあるので、探してみてくださ…

ちょっと待った

立ちはだかるIE11の壁

このまま「いかがでしたか?」で締めにかかろうとしたんですが、IE11が…

CSS Gridの実装はされているのですが古い仕様で実装され、挙動が違いすぎるので実質ほぼ互換性がないです。

なので、上で書いてきたCSSをそのまま実装すると、こうなります。

何も出ない…

IE11を無視すれば使える事は使えますが、まだシェア的にIE11を無視するのは非常に難しいでしょう。

(Gulpとかに入れられる「Autoprefixer」というプラグインを使う手段もありますが、導入がちょっと大変&変換後手直しが必要な時もある)

ちなみに、Windows7にプリインストールされているIE11は2020年1月にサポートが終了しますが、Windows8.1のIE11は2023年、Windows10のIE11については2025年までサポートされます。手強い…

この記事の著者

I-SEEDブログ編集部のアバター
I-SEEDブログ編集部

システム開発やWeb制作・デザイン、Webマーケティングを強みに持つI-SEEDスタッフが、さまざまなノウハウや最新情報をお届けします。

CONTACT/ お問い合わせ

システム開発やWeb制作・デザイン、Webマーケティングに関するご質問やご相談はこちらから。

お問い合わせする

ESTIMATE/ 料金シミュレーター

Web上で簡単なお見積もりが可能です。シミュレーション結果をもとにお問い合わせいただくことも可能ですので、お気軽にご相談ください。

Web見積もりをする
目次