フレキシブル ボックス モデルを使ってみる

HTML5 Rocks

はじめに

スタイリング要素をページ上で水平や垂直に配列することはよくありますが、これまで、 CSS ではこの処理に適した機能が不足していました。そこで、 CSS 3 でフレキシブル ボックス モジュール(略して「フレックスボックス」)が導入されました。

草案では、フレックスボックスを次のように説明しています(以下、リンク先はすべて英語)。

[...] インターフェース設計用に最適化された CSS のボックス モデル。 CSS の既存のボックス モデルに基づいて、追加のレイアウト システムを提供します。[CSS21] この新しいボックス モデルでは、ボックスの子を水平または垂直にレイアウトできます。拡張すべき子に「flex」を指定すると、使用されていないスペースを特定の子に割り当てたり、複数の子に分配したりできます。これらのボックスの入れ子(垂直の中に水平、水平の中に垂直)を使用して 2 次元のレイアウトを作成できます。このモデルは、多くの Mozilla ベースのアプリケーション(Firefox など)のユーザー インターフェースで使用されている、 XUL ユーザー インターフェース言語のボックス モデルに基づいています。

すばらしい機能ですね。開発者や Layout Architect™ にとっては次のようなメリットがあります。

  1. 今後はフロートの配置が不要になる可能性があります。
  2. これまで難しかったレイアウトを実現しやすくなりました。
  3. 非常にフレキシブルなレイアウトを作成可能で、ブラウザが代わりに計算してくれます。

フレックスボックスには display プロパティの新しい値(box 値)と 8 つの新しいプロパティがあります。

  • box-orient
  • box-pack
  • box-align
  • box-flex
  • box-flex-group
  • box-ordinal-group
  • box-direction
  • box-lines
新しいプロパティが 8 つもあるので、少し多いと思われたでしょうか。それでは、詳しく見てみましょう。

フレックスボックスの一般的なスタイル プロパティ

ボックスで使用されるスタイル

display: box
display スタイル プロパティにこの新しい値を指定すると、要素とその直接の子がフレキシブル ボックス モデルになります。フレックスボックス モデルは直接の子のみに使用できます。
box-orient
値: horizontal | vertical | inherit
ボックスの子の配置方法です。2 つの追加の値 inline-axis(実際のデフォルト)と block-axis がありますが、それぞれ horizontal と vertical にマッピングされます。
box-pack
値: start | end | center | justify
box-orient の軸に沿ったボックスの配置を設定します。たとえば、box-orient が horizontal の場合は、ボックスの子が水平に配列されます。
box-align
値: start | end | center | baseline | stretch
基本的には、box-pack の兄弟プロパティです。ボックス内でのボックスの子の配置方法を設定します。たとえば、方向が水平(horizontal)の場合は、水平に配置されます。

ボックスの子で使用されるスタイル

box-flex
値: 0 | 任意の整数
子のフレキシビリティ(柔軟性)の比率です。子に 1、その兄弟に 2 を指定した場合、親ボックス内の余分なスペースは 1 対 2 で分配されます(兄弟のスペースの方が 2 倍になります)。デフォルトは 0(フレキシブルなし)です。

box-flex-groupbox-ordinal-groupbox-directionbox-lines は実際のところ、フレックスボックスの処理にあまり必要ないため、ここでは説明を省略しました。これらのプロパティについて詳しくは、まとめにあるリンクをご覧ください。

構文に関する注意事項: WebKit や Gecko でフレックスボックスの現在の実装を使用するには、ベンダー プレフィックスを付ける必要があります。このチュートリアルでは、わかりやすくするため、ベンダー プレフィックスをほぼ省略しています。詳しくは、ブラウザのサポートをご覧ください。

フレキシビリティとは

box-flex スタイル プロパティでは、フレックスボックスの子をフレキシブルにするかどうかを定義し、兄弟に対して相対的なフレキシビリティの比率を指定できます。それでは、実際の例を見てみましょう。まず、3 つのボックスから始めます。
<div id="flexbox">
  <p>child 1</p>
  <p>child 2</p>
  <p>child 3</p>
</div>

3 つのボックスを順々に水平にレイアウトし、高さはそれぞれのコンテンツに関係なく常に同じにするとします。これまではどのように処理していたでしょうか。おそらく、ほとんどの場合は、これらのパラグラフにフロート(float)を使用し、フロートをクリアするために親ボックスに overflow:hidden; を追加していたのではないでしょうか。それが普通の方法でした。しかし、フレックスボックスを使うと、同じレイアウトを簡単に行えるようになります。

#flexbox { 
  display: box;
  box-orient: horizontal;
}

上記のコードでは、フレックスボックス モデルに従い、すべての子を水平軸に沿って配列するように親に指示しただけです。フロートは使用していません。

子の幅は指定されたとおりになります(指定されていない場合は、それぞれの固有の幅になります)。つまり、すべての子の幅の合計は親の全体幅より小さくなり、次のようなレイアウトになります。

親要素内で 3 つの子要素は固有の幅を維持している

デフォルトでは、フレックスボックスの子はフレキシブルではありません。意外に感じるかもしれませんが、フレキシブルにするかどうか選択する余地があるということです。では、子 1 と子 2 は特定の幅にして、子 3 は親の空いているスペースに応じて自動調整する場合は、どうすればよいでしょうか。ここで、フレックスボックスが本領を発揮します。

#flexbox { 
  display: box;
  box-orient: horizontal;
}
#flexbox > p:nth-child(3) {
  box-flex: 1;
}

ここでは、子 3 をフレキシブルに設定し、空いているスペースを占めるように指示しています。1 つの要素にのみスペースを割り当てたので、その要素が空いているスペースを「すべて」占めることになります。

3 番目の子要素がフレキシブルになり、空いているスペースを占める

ボックスの方向軸のみに沿ってフレキシブルになる点に注目してください。この場合、要素は水平にフレキシブルになっています。

box-flex の値は相対的です。そのため、子 2 と子 3 をフレキシブルにする場合は、次のようになります。

#flexbox { 
  display: box;
  box-orient: horizontal;
}
#flexbox > p:nth-child(2),
#flexbox > p:nth-child(3) {
  box-flex: 1;
}

2 つの子は空いているスペースを同じ量だけ占めることになります。つまり、空いているスペースが両者の間で等しく分割されます。

2 番目と 3 番目の子要素が親要素の空いているスペースを共有する
また、子 1、2、3 の box-flex をそれぞれ 123 に設定して、親の空いているスペースがその比率で分配される様子を確かめることもできますが、その代わりに、次の例を見てみましょう。

基本的な例

コードを調べて、下の結果を見てみましょう。

ボックスのいずれかにカーソルを置いて、フレキシブル ボックスの動きを確認してください。カーソルを置くとそのボックスが拡張して、他のボックスのサイズが小さくなりますが、全体の幅は親ボックスのサイズと常に一致しています。

ここでは実際には 2 つのスタイルしか使っていません。display: box を指定すると要素がフレックスボックス モードになります。子に対して box-flex: 1 を指定すると、子がフレキシブル モードで動作し、余分なスペースをすべて占有します。デフォルトの方向は水平なので、実際には box-orient: horizontal は必要ありませんが、指定しておくと明確で管理しやすくなります。デフォルトの box-align は stretch なので、これらの div(子ボックス)が親ボックスの高さ全体を占めています。いかがでしょうか。このテクニックをナビゲーションに活用した例として、Raphael Goetter 氏によるこちらのデモをご覧いただけます。

この手法をぜひご利用ください。

センター ステージ: 中央配置

CSS では長い間、要素を水平または垂直に中央配置するのが難しい課題でした。最適で唯一の解決策は、「position:absolute; left: 50%; top: 50%;」と指定し、左と上の余白(margin)にそれぞれ幅と高さの半分に相当する負の値を指定する方法でした。そして、この方法は明示的にサイズを指定した要素にしか使用できません。

James John Malcom 氏は display:table-cell; を使って垂直に配置する方法があると知らせてくれましたが、6 年以上前のことになります(Dušan Janovský 氏がこの件について 2004 年に投稿してくれました)。James 氏による水平および垂直の中央配置に関する詳しい解決策については、こちらをご覧ください。明示的にサイズを指定した要素がなくても機能する方法です。

フレックスボックスを使えば、簡単に行えるようになります。

空いているスペースを子に使わせたくないため、子に対して box-flex を設定していません。サイズに関係なく中央に配置するだけです。この方法の大きなメリットは、中央配置するためにサイズを明示的に指定する必要がない点です。一般的なブロックやインラインなどで、この方法を問題なく利用できます。

ブラウザのサポート

フレキシブル ボックス モデルは今すぐに利用できるのでしょうか。すべてのブラウザを対象とする場合は、まだ難しいと言えます。IE9 や Opera 10.60 にはまだフレックスボックスが導入されていないようですが、確認したのは IE9 プラットフォームのプレビュー版だったため、Microsoft が今後追加する可能性があります。

Caniuse.com では現在のブラウザのサポート状況が報告されており、基本的には、Firefox 3 以上、Safari 3 以上、Chrome でサポートされています。モバイル ウェブキットの開発を行っている場合は、標準のレイアウト方法の代わりとしてフレックスボックスが大変役立ちます。

しかし、まだ試験的な段階のため、ベンダー プレフィックスを付けるようおすすめします。

/* i wish it was as easy as this: */

display: box;
box-orient: horizontal; 
box-pack: center;
box-align: center;
  
/* but in reality you'll need to do this: */

display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: center;
-webkit-box-align: center;

display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-pack: center;
-moz-box-align: center;

display: box;
box-orient: horizontal;
box-pack: center;
box-align: center;
  

入力が大変だと思われた場合は、Alex Russell 氏がこれらのオプションをすべて抽出した便利なヘルパー クラスを作成してくれましたので、ご利用ください。

まとめ

今回は残りの 4 つのプロパティを検討しませんでしたが、それでも可能性が大きく広がりました。フレックスボックスをさらに調べるには、Isotoma のフレックスボックス デモや、Mozilla Hacks のフレックスボックスに関する投稿をご覧ください。W3C のフレックスボックス仕様にはさらに詳しく記述されていますので、よろしければご覧ください。すばらしいレイアウトの設計をどうぞお楽しみください。

このチュートリアルの一部は Stephen Hay 氏によるガイドに基づいています。同氏は自著について CC-by のライセンスを許可しています。

Comments

0