HTML5Experts.jp

これからのCSSはmargin禁止!?CSSグリッドレイアウトやコンポーネント指向なCSSについて、矢倉さんに聞いてきた!

こんにちは、編集長の白石です。

この記事は、9月24日に開催されたHTML5 Conference 2017に登壇したエキスパートに、お話されたセッションのトピックを中心に語っていただこうとういものです。セッションの内容をより深く理解する手助けになるだけでなく、本記事単体でも面白く読んでいただけることを目指しています。

今回お話を伺ったのは、ピクセルグリッドの矢倉眞隆さんです。

矢倉さんのセッション「まあまあ最近のCSSとつらくならないための書き方」に関するスライド資料は、こちらで公開されています。

インパクト大!CSSグリッドレイアウト概要

白石: では、まずは簡単に自己紹介をお願いできますか?

矢倉: 昨年(2016年)から、ピクセルグリッド という会社で働いています。役割としては、CodeGridというフロントエンド向けメディアの運営を担当しています。

CodeGridは自社のメディアなので、技術的なチャレンジなどを行いやすいんです。なので今回のHTML5 Conferenceのセッションでは、CodeGridでの経験を基に、今後のWeb制作においてCSSの書き方がどう変わっていくかをお話ししました。

白石: 具体的には、どんなチャレンジを行ったんですか?

矢倉: CSSグリッドレイアウトを使ってみたんです。

ページのレイアウトを行う方法は、古くはtableを使ったものからfloatを使った手法、最近だとFlexboxを使ったものまで、様々な手法が使われてきました。グリッドレイアウトは、そうしたレイアウトテクニックの中でも最も新しくて、CSSの書き方を一変させる可能性のある仕様だと思います。

白石: それほどインパクトのある仕様なんですね。CSSグリッドレイアウトについて、まずは概要を教えていただけますか?

矢倉: グリッドレイアウト自体は、実は結構古くから提案されている仕様なんです。2000年代前半にマイクロソフトが提案していて、ベンダープレフィックス付きの実装はInternet Explorer 10から提供されていました。

どのような仕様かというと、名前の通り、CSSでグリッドベース(格子状)のレイアウトを可能にするものです。

CSSでグリッドレイアウトを行うためのフレームワークは、これまでも数え切れないほど提案されてきました。ニーズは非常に高かったんですね。ただ、標準として提供されている機能はなかったため、いろいろと不便なシーンもありました。グリッドを実現するために不要なdiv要素を数多く書く必要があったり、機能が高くなかったり…。

Sketchなどのプロトタイピングツールで行ったデザインを、Webデザインで再現するのが難しいのも、グリッドの機能がWebに足りなかったという理由が大きいと思っています。

そうしたグリッドレイアウトの機能を標準で提供するのがCSSグリッドレイアウトなんです。

白石: なるほど。歴史もニーズもある、待ち望まれた機能ということですね。ブラウザが標準でサポートすることで、どういうメリットがあるんでしょうか?

矢倉: まず、レイアウト用の余計なdivが減ります。またこれは憶測でしかないのですが、ブラウザがグリッドレイアウトの処理を最適化できれば、floatなどのレイアウトなどと比べ、パフォーマンスの向上も期待できるかもしれません。

あと、マークアップもよりシンプルになると思いますね。要素をグリッド内に自在に配置できるので、DOMの順序にそれほど左右されずにレイアウトができるんです。

白石: それは素晴らしい。今までは、どうしてもマークアップがどうしてもUIデザインに引きずられちゃう場面もありましたものね。

矢倉: 実際には、グリッドのアイテムに指定できるのはグリッドコンテナ直下の要素に限られていたりするので、マークアップ上の制約が全くないわけではないですけどね。ただ、レイアウト用のdiv要素を記述する場面はかなり減って、より素直なマークアップがやりやすくはなったな、と思います。

白石: CSSグリッドレイアウトは、現在どれくらいのブラウザが対応しているんですか?

矢倉: メジャーブラウザはほとんど対応済みで、Firefox, Chrome, Safariの最新版は全て対応しています。Edgeは、先日のWindows 10 Fall Creators Updateで対応しました。IE/Edgeは、古いプレフィックス付きのバージョンをサポートしていますで対応しています。

特に、Safariが10.1から対応したのは大きいですね。iOSでもかなりの割合で使えるようになったので、モバイルブラウザでの対応が大きく進みました。

白石: かなり新しい技術かと思ってましたが、もう使えるブラウザはかなり多いんですね。

矢倉: はい、Can I Useの結果を見ると、世界全体で見ると75% (プレフィックス付きを除くと69%) のブラウザで利用できるようです。

ちなみにCan I Useには、Google Analyticsと連動させる機能があるんです。そうすると、サイトを利用しているブラウザの統計から、そのサイトに限定した結果を得ることができます。

私が担当しているCodeGridは開発者向けの媒体で、新しめのデバイスやOSを利用してらっしゃる方が多いので、グリッドレイアウトが利用可能なユーザーの割合が実に95%以上に上りました。これが、私がCodeGridでグリッドレイアウトを試してみようと思った理由の一つでもあります。

Can I UseでのCSSグリッドレイアウト利用可能率

白石: Can I Use、そんな機能あったんですね…!知りませんでした。

CSSグリッドレイアウトのつかいかた

白石: では、グリッドレイアウトを使ったスタイリングの方法を教えてください。

矢倉: はい。実は、基本的な使い方はかなり簡単です。

まず基本的な考え方としては、グリッドレイアウトはまずグリッドの線を引いてから、そこに要素をあてがっていくという流れになります。

例えば、ヘッダー領域とコンテンツ領域を持つ、以下のようなレイアウトを行いたいとしますよね。

で、このようにマークアップされていたとします。

<div class="layout">
  <div class="header"></div>
  <div class="content"></div>
</div>

まずグリッドレイアウトを行うには、レイアウトのコンテナとなる要素に対してdisplay: grid;を指定します。

.layout {
  display: grid;
}

次にグリッド線を引いていきましょう。まずは縦線(列)の定義です。今回は、左右に固定で50pxを確保し、残りがコンテンツの幅になるように指定します。

以下のように指定します。

.layout {
  grid-template-columns: 50px 1fr 50px;
}

これで、以下のようなグリッド線を定義したことになります。

次は横線(行)を引いていきましょう。ヘッダーに30px、フッターに150pxを確保して、残りがコンテンツの高さになるようにします。

.layout {
  grid-template-rows: 30px 1fr 150px;
}

これで、横方向のグリッド線も引くことができました。

あとは、完成したグリッドに要素を割り当てていきます。グリッド線にはそれぞれ1から始まる(末尾から数える場合は-1から始まる)番号が自動で割り振られるので、それぞれの要素の開始位置と終了位置を指定します。

/* 1行目はヘッダー /
.header {
  grid-row-start: 1;
  grid-row-end: 2;
  grid-column: 1 / -1;
}
/ 2行目の真ん中がコンテンツ */
.content {
  grid-row: 2 / 3;
  grid-column: 2 / -2;
}

これが基本的な使い方で、他にも、グリッドの範囲に名前を付けて要素を配置することもできたりします。

コンポーネント指向の時代に備えてスタイリングしよう!

白石: では、先ほどおっしゃっていた 今後のWeb制作においてCSSの書き方がどう変わっていくかというのは、具体的にはどのようなことでしょうか?

矢倉: 結論から言うと、グリッドレイアウトを使ってみた結果、コンポーネント指向なWebアプリ開発に通じるところがとても大きいと感じたんです。

白石: コンポーネント指向というと、Web ComponentsやReactでいうコンポーネントでしょうか?

矢倉: はい、そうです。順を追ってお話しますね。

まず、私は既存のWebページ(CodeGrid)を修正してグリッドレイアウトを使うように見直していました。つまり、既存のスタイル定義がたくさん存在する状態です。

そしてグリッドレイアウトを行うには、先ほどお話ししたように、グリッドを先に定義してそこに要素を当てはめていきます。

ただ、グリッドに要素をぴったり沿わせるためには、個々の要素に既に当たっているマージンが邪魔だったんですよ。

白石: なるほど。個々の要素がそれぞれバラバラにマージンを持っていたら、グリッド内の余白もチグハグになってしまいそう。

矢倉: そうなんです。

グリッド内の個々の要素がマージンを持つんじゃなくて、グリッドのセルにあたる要素がパディングを使って余白を指定するほうが柔軟だし、管理もしやすいんです。

ただ、既存のWebページ上にはマージンの指定って至るところにあって、それらを見直していくのはなかなか大変な作業になるなと気づきました。

白石: 確かに、マージンって位置合わせのために、結構カジュアルに使いますものね。

矢倉: ここから得た学びが、「グリッドレイアウトを使う際には、個々の要素にマージンを指定するのは良くない」ということでした。

でも、そこからさらに考えを進めると、グリッドレイアウトだけではなく、コンポーネント指向なWebデザイン全般にも適用できる考え方じゃないかと思えてきたんです。つまり、「個々のコンポーネントにマージンを指定するのは良くない」ということです。

白石: グリッドレイアウトにすると、DOMの順序からも解き放たれるくらい、グリッドの要素の独立性が高まる。だから結局それらが「コンポーネント」として独立したものと見なせるようになったということかもしれませんね。

矢倉: そうです。グリッドの要素それぞれをコンポーネントと見なすようになると、要素間の空白も含めて、その配置はコンポーネントのコンテナに全て任せるべきなんです。コンポーネントの責任範囲はその内側だけに絞るべきで、その「外側」であるマージンをコンポーネント自身がコントロールすべきじゃない。

白石: なるほど…つまり、コンポーネント時代のCSSではマージンの指定を禁止するというくらいやっちゃってもいいのかもしれませんね。

矢倉: はい、そこまで徹底したルールにして、CSS Lint (CSSスタイルのチェックツール)とかで禁止しちゃってもいいかな、位に思っています。

コンポーネント間の空白については、その外側の要素がパディングで指定するようにすればいい。実際にはp要素の空白など、marginを使わないとうまく指定できないものも存在しますので、「コンポーネントの外側にマージンを指定するのは禁止」くらいのルールになるかな、とは思いますけどね。

ついでに言うと、メディアクエリもコンポーネント指向には向きません。メディアクエリを使うと、「コンポーネント自身がメディアに応じてスタイルを変える」というCSSをカジュアルに書けすぎてしまうんです。それだと、コンポーネントを別の場面で再利用しようと思った時に、使いづらいものになってしまいがちです。

コンポーネント自身は、(コンテナに)流し込まれるものであるべき。自身が幅いっぱいに広がるものとしてデザインすべきだと思います。

白石: 確かに、理にかなってますね。でも、ぼく今でもマージン使いまくりだなあ…(汗)。

矢倉: 今までは「マージン禁止」なんて誰も言いませんでしたものね(笑) 。でも今後はそういうスタイリングが一般的になっていくんじゃないかな、と思います。

あと、今までCSSの文脈で話していましたが、こういう考え方は、ReactやVue.jsなどのコンポーネント指向フレームワークとも通ずるものがあると思うんです。

そうしたフレームワークを使ってコンポーネント設計を行う時のベストプラクティスとして、コンテナ・コンポーネントとプレゼンテーショナル・コンポーネントに分けるという考え方も主流になりつつありますし(※)。

※コンポーネントを二種類に分け、プレゼンテーショナル・コンポーネントは単純な表示のみを行い、それらが配置された不可視のコンテナ・コンポーネントが振る舞いを一括で管理する、という設計思想のこと。出自はこちら

白石: 確かに、そうした考え方とも非常に良くマッチしそうですね。CSSにおいても、コンポーネント間の責務を真剣に考えるときが来たということでしょうね。

本日は興味深いお話、どうもありがとうございました!

(写真提供:html5j、撮影:刑部友康)