これからのグリッドレイアウト 第1回 Grid Layout Moduleの概要

まずはdisplay:grid;を核とするGrid Layout Moduleがどのような仕様か、その概要を紹介します。さらに、指定の基本となるグリッドコンテナとグリッドアイテムという概念ついて解説をします。

発行

著者 坂巻 翔大郎 フロントエンド・エンジニア
これからのグリッドレイアウト シリーズの記事一覧

はじめに

筆者とdisplay:grid;の出会いは、この記事が書かれる4年前の2012年3月頃になります。2011年6月末にIE10PP(Platform Preview)が登場した時に、IE10PPがプリフィックス付きでdisplay:-ms-grid;を実装していました。

いろいろとCSSに関する調べ物をしていた際に、「IE10PPではGrid Layout Moduleが使えるらしい。」ということで、display:-ms-grid;を使ったサンプルを作り遊んでいました。

グリッド・カラムレイアウトといえば、以前紹介したFlexible Box*やdisplay:table;を利用したマルチカラムレイアウト*などがあります。また、CodeGridではまだ紹介していませんが、CSS Multi-column Layout Moduleもマルチカラムレイアウトをする上で重要です。

*注:Flexible Boxやマルチカラムレイアウト

CodeGridでは以下の記事で紹介しました。

今回紹介するGrid Layout Moduleの核となるdisplay:grid;は、グリッドレイアウトをする上では、とても強力で、役に立つプロパティになります。

ブラウザの実装が進み、徐々に使われるようになっていると思われるdisplay:flex;や、display:table-cell;などでも手の届かなかった部分を解決してくれるでしょう。

本記事では、このGrid Layout Moduleについて解説していきます。まず仕様に登場する用語の解説をした後に、実際にはどういったレイアウトが実現できるか、そのサンプルをコードとともに紹介していきます。

各ブラウザの実装状況

2011年から5年経ちましたが、実装状況はあまり芳しくありません。それでも、進捗がゆっくりであるというだけで、現在のところ実装は着実に進んでいるように思えます。

執筆時点で参考にしている仕様書は、CSS Grid Layout Module Level 1 | W3C Working Draft, 17 September 2015です(最新)。日本語訳はCSS Grid Layout Module Level 1 日本語訳を参照しています。

また、2016年1月27日現在、ChromeやFirefoxを含め、どのブラウザでも動作を確認することができません。ですが、ChromeとFirefoxは、高度な設定を変更することで、display:grid;に関する機能を有効にできます。

筆者はChrome Canary v50*で、「試験運用機能」の「試験運用版のウェブ プラットフォームの機能」項目(chrome://flags/#enable-experimental-web-platform-features)を有効にして、後述するコードを確認しています。

*注:Chrome Canary

ChromeのCanaryを使うのはちょっとした理由があります。普段、実務で使っているChromeの安定版でいろいろ試してしまうと、うっかりフラグを立てたまま、万が一の間違いがあるといけないからです。ブラウザに限らず、可能であれば、テスト環境は普段の実務で使う環境と分けて管理するとよいでしょう。

何ができるのか

Grid Layout Moduleでは、CSS上でレイアウト情報を定義することができます。display: grid;が指定された親要素にグリッドレイアウト情報を定義し、子要素では、そのグリッドのどこに配置されるかを定義します。

table要素を利用したテーブルレイアウトと似たように思えますが、table要素がHTML側でレイアウト構造を指定するのに対し、Grid Layout ModuleではCSS側で、どのようなレイアウト構造にするかを指定するという違いがあります。

文章だけで表現すると、初見で理解するのは難しいので、まずは簡単なサンプルを紹介します。いったんコードについての具体的な解説を省略して、Grid Layout Moduleの雰囲気を掴んでいただければと思います。

このサンプルでは、ゲームの画面のようなものをイメージしています。

広い画面の場合と、狭い画面になった場合でレイアウトを変更しています。これをGrid Layout Moduleを使い、実現します。

まずはHTML部分です。HTMLの構造は非常に単純です。

<div class="grid">
  <div class="title">Title</div>
  <div class="status">Status</div>
  <div class="memberList">Member List</div>
  <div class="gameWindow">Game Window</div>
  <div class="chatWindow">Chat Window</div>
</div>

次にCSS部分です。display: grid;などを使用して、レイアウト情報を指定します。画面幅が狭くなったときには、メディアクエリでレイアウトを再定義しています。

/* landscape */
.grid {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr auto;
}
.title {
  grid-area: 1 / 1;
}
.status {
  grid-area: 3 / 1;
}
.memberList {
  grid-area: 2 / 1;
  align-self: start;
}
.gameWindow {
  grid-area: 1 / 2 / span 2 / auto;
  height: 250px;
}
.chatWindow {
  grid-area: 3 / 2;
}
/* portrait */
@media (max-width: 450px) {
  .grid {
    grid-template-columns: 150px 1fr;
    grid-template-rows: auto auto auto auto;
    grid-template-areas: "title   list"
                         "status  list"
                         "game    game"
                         "chat    chat";
  }
  .title {
    grid-area: title;
  }
  .status {
    grid-area: status;
  }
  .memberList {
    grid-area: list;
    align-self: stretch;
  }
  .gameWindow {
    grid-area: game;
  }
  .chatWindow {
    grid-area: chat;
  }
}

たったこれだけで、HTMLの構造からは想像しづらいレイアウトを実現することができます。このデモを新しいウィンドウで開き、ウィンドウサイズを変化させてみると、レイアウトが変更されることを確認できるはずです。

対応していないブラウザの方は、その変化の様子をアニメーションGIFで確認してください。

本連載では執筆時点(2016年2月)での最新のシンタックスについて解説していくため、古い仕様を元に実装されているIE10以上とEdgeでは確認することができません。記事中で紹介するコードを確認する際は、試験運用機能を有効にしたChromeやFirefoxを利用してください。

筆者が最初Grid Layout Moduleの仕様を読んだときは、「これは人間の書くものではないのでは……」と感じました。執筆中も同じように感じています。ですが、将来的に使えるようになれば、非常に強力な仕様ですので、この連載を通してGrid Layout Moduleの理解を深めていきましょう。

コラム:古いシンタックスと最新のシンタックス

冒頭でも述べましたが、Grid Layout ModuleはIE10以降やEdgeで使用することができました。ですが、2011年頃の仕様(Grid Layout | W3C Working Draft 7 April 2011)を元にしています。そのため、ChromeやFirefoxの先行実装が元にしている2015年版の仕様との差が生まれています。本記事では、2015年版の最新の仕様について解説していくため、IEが対応している古い仕様については解説しません。また、最新の仕様の中でもChromeが対応していないプロパティや値に関しては解説していません。

もしIE10以降やEdgeにも対応したい場合は、Autoprefixer*を併用することをおすすめします。この記事の執筆中にAutoprefixerのバージョンが上がりました(6.3 “Pro rege et lege”)。このアップデートで、最新の仕様に沿った記述をすれば、IE用の記述にも対応ができるようになります。ですが、すべてのGrid Layout Moduleに関するプロパティが古い仕様に対応しているわけではないので注意が必要です。

*注:Autoprefixer

Autoprefixerに関しては、次の記事を参照してください。

Grid Layout Moduleに登場する用語

Grid Layout Moduleの理解を深めるには、まず、登場する用語とその意味を知っておく必要があります。頻繁に使う用語としては、次の用語があります。それぞれ関係がある用語ですので、順番に追っていけば、そんなに混乱することはないと思います。

  • グリッドコンテナ
  • グリッドアイテム
  • グリッドライン
  • グリッドトラック
  • グリッドセル
  • グリッドエリア

今回は、Grid Layout Moduleに登場する用語の中でもっとも基本的な、グリッドコンテナとグリッドアイテムについて解説します。解説の中には、まだ説明されていない用語が出てくることもありますが、回を追って、すべて説明をしていきます。

グリッドコンテナとグリッドアイテム

もっとも基本的な概念として、グリッドコンテナとグリッドアイテムがあります。Flexible Boxの中で登場したフレックスコンテナとフレックスアイテム*のような親子関係です。

*注:フレックスコンテナとフレックスアイテム

フレックスコンテナとフレックスアイテムについては以下を参照してください。

グリッドコンテナ

display: grid;またはdisplay: inline-grid;が指定された要素をグリッドコンテナと呼びます。グリッドの分割数や、分割されたグリッドの列や行の幅や高さといった、レイアウト情報を指定することができます。

たとえば、グリッドコンテナで100pxずつの2列2行のグリッドを作成する場合は、次のようなCSSを記述します。grid-template-columnsが列、grid-template-rowsが行です。

<div class="grid"></div>
.grid {
  display: grid;
  grid-template-columns: 100px 100px;
  grid-template-rows: 100px 100px;
}

グリッドコンテナに関連するプロパティは、次の通りです。

`grid`
`grid-template`、`grid-auto-flow`、`grid-auto-rows`、`grid-auto-columns`を指定できるショートハンドプロパティ
`grid-template`
`grid-template-columns`、`grid-template-rows`、`grid-template-areas`を指定できるショートハンドプロパティ
`grid-template-rows`
行のグリッドトラックそれぞれのサイズを指定する
`grid-template-columns`
列のグリッドトラックそれぞれのサイズを指定する
`grid-template-areas`
名前の付いたグリッドエリアを指定する
`grid-auto-flow`
明示的に配置されていないグリッドアイテムの配置方法を指定する
`grid-auto-rows`
自動生成される行のグリッドトラックそれぞれのサイズを指定する
`grid-auto-columns`
自動生成される列のグリッドトラックそれぞれのサイズを指定する
`grid-gap`
`grid-row-gap`、`grid-column-gap`を指定できるショートハンドプロパティ
`grid-row-gap`
行と行の間の余白を指定する
`grid-column-gap`
列と列の間の余白を指定する
`justify-items`
グリッドアイテムの横方向の整列を指定する
`align-items`
グリッドアイテムの縦方向の整列を指定する
`justify-content`
グリッドトラックの横方向の整列を指定する
`align-content`
グリッドトラックの縦方向の整列を指定する

これらのプロパティを駆使して、レイアウト情報を指定します。

justify-contentalign-content*などは、Flexible Boxで解説したものと同じです。

*注:justify-contentalign-content

詳しくは次の記事などを参照してください。

グリッドアイテム

グリッドコンテナの直下の子要素をグリッドアイテムと呼びます。グリッドアイテムには、分割されたグリッドのどこに位置するかなどを指定します。

たとえば、前述のグリッドコンテナで100pxずつの2列2行のグリッドを作成した場合、グリッドアイテムを配置する場合は、次のような記述になります。

<div class="grid">
  <div class="grid__item-1">item</div>
  <div class="grid__item-2">item</div>
  <div class="grid__item-3">item</div>
  <div class="grid__item-4">item</div>
</div>

```css
.grid {
  display: grid;
  grid-template-columns: 100px 100px;
  grid-template-rows: 100px 100px;
}
.grid__item-1 { grid-column: 1; grid-row: 1; }
.grid__item-2 { grid-column: 2; grid-row: 1; }
.grid__item-3 { grid-column: 1; grid-row: 2; }
.grid__item-4 { grid-column: 2; grid-row: 2; }

グリッドアイテムに関連するプロパティは、次の通りです。

`grid-area`
`grid-row-start`、`grid-column-start`、`grid-row-end`、`grid-column-end`を指定するショートハンドプロパティ
`grid-row`
`grid-row-start`、`grid-row-end`を指定するショートハンドプロパティ
`grid-row-start`
行の開始位置を指定する
`grid-row-end`
行の終了位置を指定する
`grid-column`
`grid-column-start`、`grid-row-end`を指定するショートハンドプロパティ
`grid-column-start`
列の開始位置を指定する
`grid-column-end`
列の終了位置を指定する
`justify-self`
横方向の整列を指定する
`align-self`
縦方向の整列を指定する
`z-index`
グリッドアイテムの重なり順を指定する

align-self*は、Flexible Boxで解説したものと同じです。justify-selfはグリッドアイテムに指定できる新たなプロパティです。

*注:align-self

詳しくは次の記事などを参照してください。

グリッドアイテムにz-indexプロパティ値のauto以外を指定した時は、positionプロパティ値がstaticであってもスタック文脈を形成します。グリッドアイテム同士が重なる場合はz-indexプロパティを指定することで、それぞれの重なり順を操作することができます。

まとめ

今回はひとまず基本となる概念、グリッドコンテナとグリッドアイテムについて解説しました。次回はさらにグリッドを基本とするレイアウトに必要な概念と、その実装について解説を進めていきます。じっくりお付き合いください。