CSS3 Flexible Box (可変ボックス)、または flexbox は、ページレイアウトを様々なスクリーンサイズやディスプレイデバイスに適応しなければならない場合に、ページ上の要素が指定した通りに配置されるレイアウトモードです。多くのアプリケーションにおいて、flexible box モデルは、float を使わず、そして flex container のマージンがそのコンテンツのマージンを相殺することも無く、block モデルを超えるための手段を提供します。
多くのデザイナーが、flexbox モデルを使いやすいと感じるでしょう。flexbox の子要素は任意の方向にレイアウトすることができ、またディスプレイの領域に適応する柔軟な寸法を持つこともできます。要素の表示順はソースコードでの順序に依存しないため子要素の配置はとても容易であり、また複雑なレイアウトをきれいなコードでシンプルに実現できます。この独立性は視覚的なレンダリングにのみ意図的に影響させており、読み上げ順やソースでの順序に基づくナビゲーションには影響しません。
Flexible box のコンセプト
flex レイアウトを定義するねらいは、アイテムの幅や高さを、任意のディスプレイデバイスで使用できる領域を最適に埋めるように変更する能力です。flex コンテナはアイテムを、使用可能な空き領域を埋めるように引き延ばしたり、はみ出さないように縮めたりします。
flexbox レイアウトのアルゴリズムは、垂直方向に偏向した (vertically-biased) block レイアウトや水平方向に偏向した (vertically-biased) inline レイアウトとは対照的に、方向について独断的ではありません (direction-agnostic)。block レイアウトはページに対して良好に働きますが、ユーザエージェントの変更や水平・垂直の切り替えなどによる向きの変化・リサイズ・拡大・縮小が必須であるアプリケーションコンポーネントをサポートするのに十分な定義がありません。Flexbox レイアウトはアプリケーションのコンポーネントや小規模のレイアウトにもっとも適している一方で、(新興の) Grid レイアウトは大規模なレイアウトを意図しています。どちらも、さまざまなユーザエージェントや記述様式や他の柔軟性に関する要求を伴う Web アプリケーションの高い相互運用性を提供するための、CSS Working Group による多大な努力の一部です。
Flexible box の用語
flexible の議論では水平/inline 軸や垂直/block 軸といった用語から解放される一方で、モデルを適切に説明するための新たな用語が必要になります。後述の語彙アイテムを復習するときは、以下の図について考えてみましょう。これは row
方向の flex-direction
を持つ flex container であり、flex item は要素のテキストフローの方向 (この場合は左から右) によって確立した記述様式に従って、main axis にまたがってお互いに水平方向に続くということです。
- Flex container (Flex コンテナ)
- flex アイテムを含む親要素です。flex コンテナは
display
プロパティの値にflex
またはinline-flex
を指定することによって定義されます。 - Flex item (flex アイテム)
-
flex コンテナの子要素が flex アイテムとなります。flex コンテナの直接の子要素になっているテキストは、無名の flex アイテムに包まれています。
- Axis (軸)
-
すべての flexible box は 2 つの軸を持っています。主軸 (main axis) は flex アイテムのいずれに対しても平行な軸です。交差軸 (cross axis) は main axis に対して垂直な軸となります。
flex-direction
プロパティは、主軸を定義します。justify-content
プロパティは、現在の行で flex アイテムをどのように主軸に沿ってレイアウトするかを定義します。align-items
プロパティは、現在の行で flex アイテムをどのように交差軸に沿ってレイアウトするかの既定値を定義します。align-self
プロパティは、align-items
プロパティで定義した既定値を上書きすることにより、ひとつの flex アイテムを交差軸上でどのように配置するかを定義します。
- Direction (方向)
-
flex コンテナの端部である main start/main end および cross start/cross end は、flex アイテムのフローの始点と終端を表します。flex アイテムは
writing-mode
で定義した向き (left-to-right や right-to-left など) をもとに、主軸や交差軸に従います。order
プロパティは要素を順序グループ (ordinal groups)に割り当てて、どの要素が最初に現れるかを決めます。flex-flow
プロパティは、flex アイテムをレイアウトするためのflex-direction
およびflex-wrap
プロパティをまとめたものです。
- Line (ライン)
-
Flex アイテムは
flex-wrap
プロパティに基づいて、単一の行または複数の行に渡ってレイアウトできます。このプロパティは、交差軸の方向や新しい行が積み重なる方向を制御します。 - Dimension (寸法)
-
flex アイテムでは、高さや幅に相当する独断的でない同等物を main size および cross size としており、これらはそれぞれ flex コンテナの主軸および交差軸に従います。
min-height
およびmin-width
プロパティの初期値は 0 です。flex
プロパティは、flex アイテムの柔軟性を定めるためのflex-grow
、flex-shrink
、flex-basis
プロパティをまとめたものです。
flexible box の指定
要素がこのスタイルを使用するように指定するには、以下のように display プロパティを指定してください:
display : flex
または
display : inline-flex
これにより当該要素を flex コンテナとして、また子要素を flex アイテムとして定義します。値 flex
は flex コンテナをブロックレベル要素にします。値 inline-flex
は、flex コンテナを極小のインラインレベル要素にします。
display : -webkit-flex
となります。flex アイテムで考慮すべき事柄
flex コンテナの直接の子要素になっているテキストは、無名の flex アイテムに包まれています。しかし、ホワイトスペースのみを含む無名の flex アイテムはレンダリングされません。これは、display: none
が指定されたような状態です。
flex コンテナの子要素で絶対的に配置したものは、静的な位置が flex コンテナの main start 側の content-box の隅に対して決められるように配置されます。
隣接する flex アイテムのマージンは相殺しません。auto
マージンを使用すると垂直方向または水平方向に追加のスペースを取り込みますので、flex アイテムの整列や分離に使用できます。詳しくは W3C Flexible Box Layout Model 仕様書の Aligning with 'auto' margins をご覧ください。
flex アイテムの合理的な最小サイズを確保するために、min-width:auto
および/または min-height:auto
を使用しましょう。flex アイテムでは auto
属性値でアイテムの幅や高さを、内容物の幅や高さを下回らないように算出して、アイテムが内容物を保持するのに十分な大きさでレンダリングされることを保証します。詳しくは min-width
および min-height
をご覧ください。
flexbox の整列関連プロパティは CSS における他のセンタリング方式とは異なり、"真の" センタリングを行います。これは、flex アイテムは flex コンテナからはみ出す場合でも中央に置かれるということです。しかし、時に問題になることがあります。ページの上端や左端 (英語など LTR 言語の場合。アラビア語など RTL 言語では右端で問題が起きます) を超えてアイテムがはみ出すとき、内容物があってもその領域にスクロールできません! 将来のリリースでは、整列関連のプロパティが "安全" なオプションも持つように拡張される予定です。現時点では、この懸念がある場合はセンタリングにマージンを使用するとよいでしょう。こちらは "安全な" 手段で対応して、はみ出す場合にセンタリングしないためです。align-
プロパティを使用する代わりに、センタリングしたい flex アイテムで auto マージンを置いてください。また justify-
プロパティを使用する代わりに、flex コンテナ内の最初と最後にある flex アイテムの外側の端に auto マージンを置いてください。auto マージンは "柔軟" かつ余分なスペースを前提としており、余分なスペースがある場合は flex アイテムをセンタリングを行い、スペースがない場合は通常の整列に切り替えます。ただし、複数行の flexbox において justify-content
をマージンによるセンタリングに置き換えようとする場合は、残念なことに各行の最初と最後の flex アイテムにマージンを置かなければなりません。どのアイテムがどの行の最後に来るかを事前に予測できるのでなければ、justify-content
プロパティを置き換えるために、主軸でのマージンによるセンタリングに頼ることはできません。
要素の表示順序はソースコードでの順序とは独立していますが、この独立性は視覚的なレンダリングにのみ影響しており、読み上げ順やソースでの順序に基づくナビゲーションには影響しないことを思い出しましょう。order
プロパティも、読み上げやナビゲーションの順序に影響を与えません。よって、開発者はドキュメントのアクセシビリティを壊さないように、ソースコードで適切に要素を並べるように気をつけなければなりません。
flexible box 関連プロパティ
flexible box に影響を与えないプロパティ
flexible box は独特のレイアウトアルゴリズムを使用するため、flex コンテナでは意味がないプロパティがあります。
- マルチカラムモジュールの
column-*
プロパティは、flex アイテムに対する効果がありません。 - flex アイテムで、
float
およびclear
は効果がありません。float
を使用すると、その要素のdisplay
プロパティはblock
であると算定されます。 vertical-align
は、flex アイテムの配置に影響を与えません。
例
基本的な flex の例
この基本的な例では要素に "柔軟性" を与える方法と、柔軟な状態で兄弟要素がどのようにふるまうかを示します。
<!DOCTYPE html> <html lang="en"> <head> <style> .flex { /* 基本のスタイルの設定 */ width: 350px; height: 200px; border: 1px solid #555; font: 14px Arial; /* flexbox の設定 */ display: -webkit-flex; -webkit-flex-direction: row; display: flex; flex-direction: row; } .flex > div { -webkit-flex: 1 1 auto; flex: 1 1 auto; width: 30px; /* transition を上手く動作させるために指定します (始めまたは終わりに "width:auto" を指定している場合の transition は現在の Gecko と Webkit では不安定です。 詳細については https://bugzil.la/731886 を参照してください) */ -webkit-transition: width 0.7s ease-out; transition: width 0.7s ease-out; } /* 色の指定 */ .flex > div:nth-child(1){ background : #009246; } .flex > div:nth-child(2){ background : #F1F2F1; } .flex > div:nth-child(3){ background : #CE2B37; } .flex > div:hover { width: 200px; } </style> </head> <body> <p>Flexbox nuovo</p> <div class="flex"> <div>uno</div> <div>due</div> <div>tre</div> </div> </body> </html>
Holy Grail レイアウトの例
この例では、flexbox がいかにしてさまざまな画面解像度に対して動的にレイアウトを変化させることを可能にするかを実証します。以下の図で、その変化を示します。
ここで示したものは、ブラウザウィンドウに適したページレイアウトをスマートフォンの画面に最適化させなければならないケースです。要素のサイズを小さくしなければならないだけでなく、要素が現れる順序も変えなければなりません。flexbox は、これをとてもシンプルにします。
<!DOCTYPE html> <html lang="en"> <head> <style> body { font: 24px Helvetica; background: #999999; } #main { min-height: 800px; margin: 0px; padding: 0px; display: -webkit-flex; display: flex; -webkit-flex-flow: row; flex-flow: row; } #main > article { margin: 4px; padding: 5px; border: 1px solid #cccc33; border-radius: 7pt; background: #dddd88; -webkit-flex: 3 1 60%; flex: 3 1 60%; -webkit-order: 2; order: 2; } #main > nav { margin: 4px; padding: 5px; border: 1px solid #8888bb; border-radius: 7pt; background: #ccccff; -webkit-flex: 1 6 20%; flex: 1 6 20%; -webkit-order: 1; order: 1; } #main > aside { margin: 4px; padding: 5px; border: 1px solid #8888bb; border-radius: 7pt; background: #ccccff; -webkit-flex: 1 6 20%; flex: 1 6 20%; -webkit-order: 3; order: 3; } header, footer { display: block; margin: 4px; padding: 5px; min-height: 100px; border: 1px solid #eebb55; border-radius: 7pt; background: #ffeebb; } /* 3 カラム表示には狭すぎる場合 */ @media all and (max-width: 640px) { #main, #page { -webkit-flex-flow: column; flex-direction: column; } #main > article, #main > nav, #main > aside { /* ドキュメントの順番に戻す */ -webkit-order: 0; order: 0; } #main > nav, #main > aside, header, footer { min-height: 50px; max-height: 50px; } } </style> </head> <body> <header>header</header> <div id='main'> <article>article</article> <nav>nav</nav> <aside>aside</aside> </div> <footer>footer</footer> </body> </html>
遊び場
実験のためにオンラインで利用できる flexbox の検証環境があります:
留意点
flex アイテムをどのようにレイアウトするかを表すアルゴリズムは、とても扱いにくい場合があります。flexible box を使用してデザインするときに、予期せぬ事態を避けるために考慮することを挙げます。
flexibles box は、記述様式に一致してレイアウトされます。これは、main start および main end が start および end の位置に従ってレイアウトされるということです。
cross start および cross end は direction
の値に依存する start または before の位置の定義に従います。
break-
プロパティで許可していれば、flexible box のレイアウト内で改ページが可能です。CSS 2.1 の page-break-before
、page-break-after
、page-break-inside
プロパティはもちろん、CSS3 の break-after
、break-before
、break-inside
プロパティが、flex コンテナ、flex アイテム、および flex アイテムの内部で受け入れられます。
ブラウザ実装状況
機能 | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
基本サポート (single-line flexbox) | 18.0 (18.0)[6]-moz[2] 22.0 (22.0) |
21.0-webkit 29.0 |
11[3] | 12.10-webkit[5] | 6.1-webkit[1] |
Multi-line flexbox | 28.0 (28.0) | 21.0-webkit 29.0 |
11[3] | 12.10[5] 15 -webkit |
6.1-webkit[1] |
機能 | Firefox Mobile (Gecko) | Firefox OS | Android | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
基本サポート (single-line flexbox) | 18.0 (18.0)-moz[2] 22.0 (22.0) |
1.0-moz[2] 1.1 |
2.1-webkit[4] 4.4 |
11 | 12.10[5] 15-webkit |
7-webkit[1] |
Multi-line flexbox | 28.0 (28.0) | 1.3 | 2.1-webkit[4] 4.4 |
11 | 12.10[5] 15-webkit |
7-webkit[1] |
[1] Safari の 6.0 まで (iOS 版では 6.1 まで) のバージョンは互換性の無い古いバージョンの草案仕様をサポートしています。Safari 6.1 (iOS 版では 7) では最終版の仕様がサポートされています。
[2] Firefox 22 まで、flexbox のサポートを有効にするには、ユーザーが about:config で設定 "layout.css.flexbox.enabled" の値を true
にする必要があります。Firefox 22 から 27 まではこの設定の既定値が true
であり、また Firefox 28 でこの設定項目を削除しました。
[3] Internet Explorer 10 は互換性の無い古いバージョンの草案仕様をサポートしています。 Internet Explorer 11 では最終版の仕様がサポートされています。
[4] Android 4.3 までのブラウザは互換性の無い古いバージョンの草案仕様をサポートしています。Android 4.4 では最終版の仕様がサポートされています。
[5] Opera 12.10 で最初に実装された flexbox
は接頭辞がありませんが、バージョン15 から 16、および Opera Mobile のバージョン 15 から 19 では接頭辞 -webkit があります。この接頭辞は Opera 17 および Opera Mobile 24 で再び削除されました。
[6] Firefox 29 まで、flex アイテムで visibility: collapse
を指定すると意図された動作である display: none
であるようには扱われず、visibility: hidden
であるように扱われます。推奨する回避策は、visibility:collapse
が指定されたようにふるまうべきである visibility:hidden
を flex アイテムに使用することです。詳しくは バグ 783470 をご覧ください。
関連情報
- さまざまなブラウザの flexbox 実装に関するバグ情報をまとめた The Flexbugs project