Webアプリケーションはいよいよ複雑化してきています。そのためフロートを使ったハック的なソリューション抜きで、もっと自然に、簡単に高度なレイアウトを実現できる方法や、手間の省けるテクニックが必要とされています。CSS Grid Layout Moduleを使って、レイアウト作成における期待の新しいソリューションを実現できます。
本記事ではこの比較的新しいCSS機能について紹介します。現時点でのブラウザーの対応状況を説明し、例を使ってCSS Grid Layout Moduleがどのように動作するかを説明します。
CSS Grid Layout Moduleとは?
Grid Layoutの背後にある中心的な概念は、Webページを列と行に分割し、作成した列と行のサイズや位置、レイヤーの定義に基づいて構成要素の位置やサイズを決定できるというものです。
グリッドを使えば、HTMLをまったく変更せずにCSSだけで要素の位置を柔軟に変更できます。メディアクエリと併用すれば、さまざまなブレークポイントでのレイアウト変更が可能です。
ブラウザーの対応状況
Grid Layoutの詳しい説明に入る前に、ブラウザーの対応状況と、現在のブラウザーでGrid Layoutを有効にする方法を確認しておくことをおすすめします。
ChromeとFirefox
すばらしいニュースがあります。2017年3月以降、ChromeとFirefoxではデフォルトでCSS Grid Layoutが使えます。
この記事の例やオリジナルの例を試すときにはChromeかFirefoxの使用をおすすめします。
Internet Explorer
Grid Layoutを最初に提案したのはマイクロソフトです。IE10ではプレフィックスとして-msを付けた形でGrid Layoutが実装されました。Can I Useで対応状況を確認すると、IE11もEdgeもGrid Layoutに対応していることが分かります。
Opera
OperaでGrid Layoutを有効にするには、ブラウザーのアドレスバーからchrome://flagsまたはopera://flags(どちらもOperaで使えます)に移動し、Enable experimental Web Platform featuresフラグを見つけてください。これを有効にしてブラウザーを再起動します。
Grid Layoutのポリフィル
そのほかのブラウザーでGrid Moduleの実装を有効にするためにポリフィルも使えます。
Grid Layoutの使用例
最初の例でGrid Layoutのすごさを実感してもらいます。そのあと、新しいコンセプトについて詳しく説明します。
ツイート、返信、検索、メッセージの4列を高さ100%でレイアウトしたTwitterアプリを、おおむね次のスクリーンショットのような感じで作成すると考えてください。
HTMLは以下のとおりです。
<div class="app-layout">
<div class="tweets">Tweets</div>
<div class="replies">Replies</div>
<div class="search">Search</div>
<div class="messages">Messages</div>
</div>
次に.app-layoutコンテナ要素にCSSを追加します。
.app-layout {
display: grid; /* 1 */
grid-template-columns: 1fr 1fr 1fr 1fr; /* 2 */
grid-template-rows: 100vh; /* 3 */
}
デモはこちらです。
上のCSSの設定内容を以下に説明します。
- displayプロパティをgridに設定
- コンテナ要素を4列に分割し、各カラムをグリッドコンテナ内の可用領域の1fr(1fraction:1フラクション)に設定
- 行数は1行とし、高さを100vh(ビューポートの高さの100%)に設定
見てのとおり、Grid Layout Moduleはdisplayプロパティに新しい値gridが追加されています。このgridという値は.app-layout要素をレスポンシブなグリッドコンテナとして設定するだけでなく、含まれるコンテンツ用に新しいグリッド整形文脈(grid formatting context)を確立します。Grid Layoutを使うにはこのプロパティが不可欠です。
grid-template-columnsプロパティはグリッド内の各グリッド列幅を指定します。.app-layoutコンテナが4列に分割され、各列は可用領域の1fr(25%)に設定されています。
grid-template-rowsは各グリッド行の高さを指定します。1行のみ作成し100vhに設定しています。
2列2行にした場合のレイアウトは次のようになります。
CSSは以下のとおりです。
.app-layout {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50vh 50vh;
}
デモはこちらです。
さらにメディアクエリでコードをラッピングすれば、上の例を小さな画面に限定して実現できます。すばらしいことに、この方法でさまざまなサイズのビューポートに合わせてレイアウトをカスタマイズできるようになります。たとえば、次のコードでは、上のレイアウトを1024px以下のビューポートに限定して適用できます。
@media screen and (max-width: 1024px) {
.app-layout {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50vh 50vh;
}
}
デモはこちらです。
Grid Layout Moduleのコンセプト
シンプルな例で説明をしたところで、Grid Layoutについてより良く理解するのに役立つ新しいコンセプトを紹介します。
■グリッドアイテム(Grid Item)
グリッドアイテムとはグリッドコンテナ(grid container)の子要素のことです。上の例で.tweets要素や.replies要素はグリッドアイテムに当たります。
■グリッド線(Grid Line)
グリッド線とは列や行の両側にある線のことです。グリッド線には2つのグループがあり、一方は列(縦軸)を、もう一方は行(横軸)を定義します。
上の図は最初の例のグリッド線を表していますが、4列をそれぞれ1frに設定したため縦線は5本になります。また行数は1行のみなので横線は2本です。
グリッドコンテナ内にグリッドアイテムをどのように配置できるか説明します。
行番号を使ってアイテムを配置
grid-column-startプロパティとgrid-column-endプロパティを使ってグリッド線番号を明確に指定できます。プロパティで開始と終了の線番号を指定します。
上の例では、ブラウザーはデフォルトで要素を以下のように配置します。
.tweets {
grid-column-start: 1;
grid-column-end: 2;
grid-row: 1;
}
.replies {
grid-column-start: 2;
grid-column-end: 3;
grid-row: 1;
}
.search {
grid-column-start: 3;
grid-column-end: 4;
grid-row: 1;
}
.messages {
grid-column-start: 4;
grid-column-end: 5;
grid-row: 1;
}
.tweet列のコードを説明すると、3本のグリッド線はCSSでそれぞれ次のような役割をしています。
- 子要素をいちばん左側の縦線から開始するように配置
- 要素を2番目の縦線で終了するように配置
- 要素を行いっぱいに配置
要素の並び順を別の位置に変更すれば上の設定を変更できます。要素を.search、.replies、.messages、.tweetsの順に配置します。
上のレイアウトは次のコードで作成できます。
.tweets {
grid-column-start: 4;
grid-column-end: 5;
grid-row: 1;
}
.replies {
grid-column-start: 2;
grid-column-end: 3;
grid-row: 1;
}
.search {
grid-column-start: 1;
grid-column-end: 2;
grid-row: 1;
}
.messages {
grid-column-start: 3;
grid-column-end: 4;
grid-row: 1;
}
さらにgrid-columnショートハンドプロパティを使うと、コード1行で開始位置と終了位置のグリッド線を設定できます。
.tweets {
grid-column: 4 / 5;
grid-row: 1;
}
.replies {
grid-column: 2 / 3;
grid-row: 1;
}
.search {
grid-column: 1 / 2;
grid-row: 1;
}
.messages {
grid-column: 3 / 4;
grid-row: 1;
}
デモはこちらです。
マークアップをまったく変更しないにもかかわらず、CSSだけでレイアウト構造を変更できました。これがGrid Layout Moduleを使う、とても大きなメリットです。ソースの記述順に関係なく要素のレイアウトを変更できるので、画面のサイズや向きが変わっても思いのままにレイアウトができるのです。
名前付き領域を使ってアイテムを配置
グリッド領域とは1つかそれ以上のグリッドアイテムのレイアウトに使用される論理空間のことです。grid-template-areasプロパティを使ってグリッド領域に明示的に名前を付け、grid-areaプロパティを使って特定の領域にグリッドアイテムを配置できます。
コンセプトをより分かりやすくするために、search列を最初に配置した4列の例を書き換えます。
.app-layout {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid
-template-rows: 100vh;
grid-template-areas: "search replies messages tweets";
}
上のコードの最終行で、グリッドコンテナを列ごとの名前で4つの名前付きグリッド領域に分割しています。次のステップでは各グリッドアイテムを名前付き領域に配置します。
.search {
grid-area: search;
}
.replies {
grid-area: replies;
}
.messages {
grid-area: messages;
}
.tweets {
grid-area: tweets;
}
デモはこちらです。
Slackのレイアウト例
Grid Layout Moduleを使ってもっと複雑な実装する場合はどうなるでしょうか。たとえばSlackのレイアウト構成要素を作成するとします。記事のテーマはレイアウトなので、Slackのデザインを簡略化して構成要素をグリッドで表現すると次のような感じになります。
このレイアウトでは縦に3列、横に3行を作成しています。グリッド線を使って次のように視覚化できます。
HTMLは次のとおりです。
<div class="app-layout">
<div class="teams">Teams</div>
<div class="channels">Channels</div>
<div class="header">Header</div>
<div class="messages">
<ul class="message-list">
<li></li>
<li></li>
</ul>
</div>
<div class="input">
<input type="text" placeholder="CSS Grid Layout Module">
</div>
</div>
CSSを以下に示します。
.app-layout {
display: grid;
height: 100vh;
grid-template-columns: 100px 250px 1fr;
grid-template-rows: auto 1fr auto;
}
grid-template-columnsプロパティを使って3列を作成していますが、1列目は100px、2列目は250px、3列目は可用領域の残りの部分を使っています。コードの最終行でグリッドの3つの行を作成しています。1行目と3行目の高さはautoに指定していますが、真ん中の行は可用領域の残りの部分を使うようにしています。
CSSの残りの部分は次のとおりです。
.teams {
grid-column: 1;
grid-row: 1 / 4;
}
.channels {
grid-column: 2;
grid-row: 1 / 4;
}
.header {
grid-column: 3;
grid-row: 1;
}
.messages {
grid-column: 3;
grid-row: 2;
}
.input {
grid-column: 3;
grid-row: 3;
}
デモはこちらです。
Slackのレイアウトは名前付き領域を使っても作成できます。デモはこちらです。
Grid Layout Module vs Flexbox
多くの人はFlexboxを使い始めているので、次の点を知りたいことでしょう。どのような場合にFlexboxを使うのが適切か、Grid Layoutを使ったほうが良いのはどのような場合か、です。
Tab Atkinsはこの点を次のように分かりやすく説明しています。
Flexboxはさまざまなレイアウトに適しているが、さらに「ページコンポーネント」要素がたくさんある場合に向いている。なぜなら、そうした要素の大半は基本的に直線的に配置されるからだ。Gridはページ全体のレイアウト、さらにはデザインが直線的とは言えない複雑なページコンポーネントに向いている。
Grid LayoutとFlexboxの2つは組み合わせ自在だ。双方が広範にサポートされるようになれば、大半のページは、全体のレイアウトとして外観はgrid、ページコンポーネントはネストされたflexboxとgridの組み合わせ、最後にテキストやコンテンツが入るページの「葉」の部分はblock、inline、tableのレイアウト、といった構成になるに違いない。
Rachel Andrewは次のように述べています。
Grid Layoutはメインページの行と列の構成に向いている。
Flexboxはナビゲーション、UI要素など直線的に配置できる要素に向いている。
CSS Grid Layout Moduleに関する資料
この記事でGrid Layoutのコンセプトやシンタックスについてすべて取り上げたわけではありません。より詳しくは以下の資料を参考にしてください。
- CSS Grid Layout Module spec(CSS Grid Layout Module仕様)
- CSS Grid Layout Examples(CSS Grid Layout例)
- Grid by Example(例で見るGrid)
- The future of layout with CSS: Grid Layouts(CSSにおけるレイアウトの今後: Grid Layout)
- Rachel Andrewのサイトの最新情報とコンテンツ。Rachel AndrewはGrid Layout関連で多くのすばらしい業績を上げている
最後に
説明してきたように、CSS Grid Layout Moduleは今後すばらしい力を発揮するでしょう。なぜならコードが簡潔で、しかもマークアップにタッチせずにレイアウト順を変更できるというメリットがあるからです。Webレイアウトの作成方法を永久的に変える点で役立つことでしょう。
※この記事は、特にCSS Grid Layoutに対するブラウザーのサポートに関して2017年3月23日に更新されました。
(原文:An Introduction to the CSS Grid Layout Module)
[翻訳:新岡祐佳子/編集:Livit]