DIST.30 「一歩差がつくCSSテクニック」にてライトニングトークをさせていただく機会がありました。この記事はそこでお話しした内容をもとに書き起こしたものです。

私が業務で携わるのはおもに、メディアサイトやコーポレートサイトのようなページ数がたくさんあるサイトの制作です。そのようなサイトでは特に、ページのテンプレートやコンポーネントをいかに堅牢な設計にできるかが重要だと感じます。

連想されるトピックとしては「CSS設計」がありますが、私見としては、CSS設計はセレクタの書き方やコンポーネントの整理の方法について述べたものであって、いかにしてレイアウトを組み立てるかという議論にはあまり踏み込んでいません。

具体的には、どのように宣言を組み合わせるか、どのようにレスポンシブにするかのような曖昧な領域については、実装において必ず意識される部分であるにも関わらず言及される場面は少ないのではないでしょうか。

背景色によってページが縦に3分割されており、そのそれぞれのブロックの中に入ったコンテンツは共通の幅で中央揃えになっている。

たとえばウェブページのレイアウトによくあるのは、エリアごとにページが背景色で区分されていて、その中に入るコンテンツのレイアウトは共通になっているパターンです。

<header>・<main>・<footer>のそれぞれの要素の中にcontainerクラスがついた<div>要素が入れ子になっている。

私ならこの実装は、背景色やエリアの内側の余白は外側の要素に持たせておいて、その中のレイアウトは同じコンポーネントとして共通化します。

一見した印象ではレイアウトはエリアごとに別々のブロックに分かれているように見えますが、細かく分解してみると、このように共通化できるパターンが見つかることがあります。

サイトでは10種類あるレイアウトプリミティブが図を伴って一覧になっている。
Layouts: Every Layout

レスポンシブデザインのためのCSSレイアウトの考え方やパターンをまとめた「Every Layout」というサイトがあります。

Every Layoutでは先ほどの中央揃えのためのボックスなど、コンポーネント単体では目に見えないようなパターンをひとつひとつ抽出してレイアウトプリミティブ(Layout primitives)と呼び、詳しく個別に解説されています。

スライドのデザインはEvery Layoutのオマージュですが、制作者であるHeydon Pickering氏にあらかじめ許諾を得ています。

レイアウトプリミティブの特徴は、特定のコンポーネントだけに依存せず、かつ複数のレイアウトプリミティブを入れ子にできることです。

そのために不可欠なのがメディアクエリによるブレイクポイントに依存しないことです。なぜならメディアクエリに依存した時点でコンポーネントの再利用性は制限されてしまうからです。

ビューポートの幅が広ければリストは1行になり、狭ければ3行に組み変わるが、ビューポートより狭い幅のボックスの中に配置されたリストは3行に組み変わらずに1行になってしまう。
The Flexbox Holy Albatross | HeydonWorks

ビューポートの幅によってボックスの行の数が切り替わるコンポーネントがあるとします。幅が広ければボックスは横に並んで、狭ければ縦に積まれる設計です。

これをメディアクエリで実装すると、ビューポート幅に応じて行の数が切り替わるようになりますが、仮にこのコンポーネントがビューポートの半分の幅のボックスの中に配置されていると、設計意図に反して狭い幅の中で無理矢理横並びになってしまいます。

つまりメディアクエリに依存するとコンポーネントを入れ子にできる組み合わせが制限されてしまうのです。レイアウトプリミティブはこのようなコンテキストに縛られないためにメディアクエリへの依存を回避しているというわけです。

ボックス状になったアラートダイアログがあり、右上に閉じるボタン、中央にメッセージ、右下に「Okay」と「Cancel」の2つのボタンが並んでいる。
Composition: Every Layout

ではアラートダイアログのコンポーネントを例にして、レイアウトプリミティブを組み合わせれば具体的にどのようなレイアウトができるのかを見てみます。

アラートダイアログには右上に閉じるボタンがあって、その下の真ん中にメッセージがあり、右下には2つのボタンが横並びになっています。汎用的なパターンに落とし込むのはなんとなく難しそうな感じがしますが、実はこのレイアウトはほとんどレイアウトプリミティブだけで成立します。

アラートダイアログは「Box」というレイアウトプリミティブがもっとも外側にあり、その内側に「Stack」があり、「Stack」の中のメッセージは「Center」、ボタンのレイアウトには「Cluster」が使われている。

Center・Cluster・Box・Stackという4つのレイアウトプリミティブを組み合わせると、このような複合的なレイアウトを汎用的なパターンとして取り扱えるようになります。

レイアウトプリミティブだけであらゆるレイアウトを実装するのは難しいですが、このようなプリミティブな型が用意されていることによってCSSのレイアウトはより簡単で単純になります。

安田祐平(やすだ・ゆうへい)

アラートダイアログのようなひとつのコンポーネント内のレイアウトだけに限らず、ページ全体のレイアウトを構成するときにもレイアウトプリミティブが役に立ちます。

たとえば私の個人サイトでは、ページ全体のほとんどのレイアウトはレイアウトプリミティブの組み合わせだけでできています。

レイアウトのパターンがレイアウトプリミティブとしてあらかじめ抽出できていると、効率的にレイアウトができて実装も単純になります。

ただレイアウトプリミティブは同じパターンを再利用する考え方が前提にあるので、CSSにおける再利用についてネガティブな印象を持っている方は敬遠してしまうかもしれません。ですがそもそも再利用が失敗を生んでしまうのは、適切な責務の切り分けができておらず抽象化に失敗していることが原因であるはずです。

レイアウトプリミティブの意味はその名の通り単純な責務を持つことです。特定のレイアウトだけの性質を純粋に表現するレイアウトプリミティブこそが、意味のある再利用を促し、CSSを堅牢なものにするのだと思います。

参考資料