[13/11/14 追記] flex-wrapの実装について注記を追加しました。
暑さもやわらいできたような気配がしてきました。皆様いかがお過ごしでしょうか。
久しぶりのブログ更新です。UIT 富田です。
今回はCSSでのレイアウトをより柔軟にしてくれるflexboxについて解説します。
flexboxは大幅な仕様の変更が過去に2度もあり、各ブラウザとそのバージョンによって実装している仕様が異なるため、後方互換をきっちり対応しようとすると、gradientと並んで2大考えるのをやめたくなるプロパティとなっております。
しかしflexboxを利用することで、現時点ではCSSだけでの対応が難しかったり、複数のプロパティを複雑に組み合わせる必要があるレイアウト(例えば一番大きい高さに揃えた要素を横に並べたり、子要素を上下左右中央位置したりといったもの)が、容易に利用できるようになるという大きなメリットもあり、使えるならば使っていきたいプロパティでもあります。
にも関わらずflexboxについて調べてみると、各仕様をまとめた記事はみつかるものの、新旧の仕様を横断的に確認できるものが見つからなかったため、後方互換をわかりやすく対応するためにまとめました。
目次
- 仕様のバージョンについて
- ベンダープリフィクスとブラウザバージョン
- 各プロパティの仕様
仕様のバージョンについて
flexboxの仕様は大きく3つの段階にわかれています。
この記事ではそれぞれbox仕様、flexbox仕様、flex仕様と呼んでいます。
box仕様
E{
display:-webkit-box;
}
というようにdisplayにboxを指定するものが最も古い仕様です。
古いchromeやiosのsafariはこちらの仕様で実装されています。
http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/
flexbox仕様
E{
display:-ms-flexbox;
}
というようにdisplayにflexboxを指定するものが、box仕様を改定したflexbox仕様です。
IE10はこちらの仕様で実装されています。
というか実装した時期の問題か、IE10以外は誰もこの仕様で実装してません。
IEェ…
http://www.w3.org/TR/2012/WD-css3-flexbox-20120322/
flex仕様
E{
display:-webkit-flex;
}
というようにdisplayにflexを指定するものが直近の仕様です。
この仕様で勧告候補になっており、ベンダープリフィクスなしで実装されるブラウザ(Firefox22やChrome28など)も出てきました。
http://www.w3.org/TR/css3-flexbox/
ベンダープリフィクスとブラウザバージョン
ベンダープリフィクスと対応するブラウザのバージョンは以下のとおりです。
Ch | Sf | ios*1 | and*2 | Fx | Op | IE | ||
---|---|---|---|---|---|---|---|---|
box | -webkit | 4-20 | 3.1-6.0 | 3.2-6.1 | 2.1-4.3+ | 12.1 | ||
-moz | 2-21 | |||||||
flexbox | -ms | 10 | ||||||
flex | -webkit | 21-27 | 6.1+ | 7+ | 15-16 | |||
接頭辞なし | 28+ | 22+ | 12.1,17+ | 11+ |
*1 iOS Safari
*2 Android Browser
http://css-tricks.com/old-flexbox-and-new-flexbox/
http://caniuse.com/flexbox
各プロパティの仕様
ここから各プロパティの仕様について説明します。
flexboxの説明ではflexコンテナとflexアイテムという用語が使われます。
次の図の通り、flexアイテムを包み込んでいる要素が、flexコンテナと呼ばれます。
flex関連のプロパティは、プロパティごとにflexコンテナ/flexアイテムのどちらに指定できるかが決まっています。これから解説する各プロパティがflexコンテナ/flexアイテムのどちらに指定できるかは、各プロパティの表の下に「対象」として記載しています。
また、プロパティ表の「値」列の太字項目はそのプロパティの初期値を指しています。
display:flex(flexコンテナ指定)
まずは、flexboxを利用する上で起点となるflexコンテナの指定です。
displayプロパティの値に「flex(inline-flex)」を指定することで、flexコンテナとなります。
flexコンテナの直下の子要素は、自動的にflexアイテムとなります。
仕様 | プロパティ | 値 |
---|---|---|
box | display | box | inline-box |
flexbox | flexbox | inline-flexbox | |
flex | flex | inline-flex |
flexbox関連プロパティのうち、displayプロパティのみ、ベンダープリフィクスを値に設定します。
その他のflexbox関連プロパティは、ベンダープリフィクスをプロパティ名に設定します
ベンダープリフィクスを使った記述例:
ul{
display:-webkit-box;
display:-webkit-flex;
-webkit-box-orient:horizontal;
-webkit-flex-direction:row;
}
li{
-webkit-box-flex:1;
-webkit-flex:1;
}
flex direction(表示方向)
flexアイテムを表示する方向について、縦横と並び順を指定します。
※ここではわかりやすくするために縦横と書いていますが、これは横書き(左から右への横書き/上から下への行送り)での垂直方向を縦、水平方向を横としたものです。
writing modeの指定によって変わることに注意してください。
仕様 | プロパティ | 値 |
---|---|---|
box | box-orient | horizontal | vertical | inline-axis | block-axis | inherit |
box direction | normal | reverse | inherit | |
flexbox | flex direction | row | row-reverse | column | column-reverse |
flex |
対象:flexコンテナ
box仕様では、box-orientプロパティとbox directionプロパティの2つで指定していましたが、flexbox仕様以降はflex directionプロパティに統合されました。
inline-axisとblock-axisについて
box-orientプロパティに指定できるキーワードのうち、「inline-axis」は「horizontal」に、「block-axis」は「vertical」にマッピングされており、それぞれ挙動も「horizontal」、「vertical」と同じものとなります。
また「inline-axis」と「block-axis」キーワードは、flexbox仕様以降は廃止されました。
reverseの並び順とwebkitでの挙動について
flexアイテムの並び順は、box directionプロパティが「normal」ではflexコンテナの左端から右方向に順にならび、「reverse」ではflexコンテナの右端から左方向に順にならびます。flex directionでもこの仕様に変わりはありません。しかし-webkit-box directionプロパティのみ、「reverse」を設定してもflexアイテムの順番が変わるだけで、最初のflexアイテムは右端に寄りません。
仕様通り右端に寄せたい場合、後述のflex-packプロパティを使う必要があります。
flexCont{
display:-moz-box;
display:-webkit-box;
-moz-box-orient:horizontal;
-moz-box-direction:reverse;
-webkit-box-orient:horizontal;
-webkit-box-direction:reverse;
/* webkit bugfix */
-webkit-box-pack:end;
}
ios、androidはbox仕様のwebkitで動作しているため、注意が必要です。
新旧仕様のキーワードの対応
box仕様のbox-orient、box directionと、flexbox仕様以降のflex directionで指定できるキーワードは、以下のように一致しています。
box-orientbox direction | flex direction |
---|---|
horizontalnormal | row |
horizontalreverse | row-reverse |
verticalnormal | column |
verticalreverse | column-reverse |
flex wrap(行制御)
flexコンテナからはみでたflexアイテムについて、そのまま一行で表示するか、折り返して複数行にするかを指定します。
※flexアイテムが並ぶ行について、以後はflex行と呼びます。
仕様 | プロパティ | 値 |
---|---|---|
box | box-lines | single | multiple |
flexbox | flex wrap | nowrap | wrap | wrap-reverse |
flex |
対象:flexコンテナ
「single / nowrap」では、改行せずにはみでたまま表示します。
「multiple / wrap」では、flexコンテナに収まるように改行して表示します。
flexbox仕様から追加された「wrap-reverse」では、flexコンテナに収まるように改行しつつ、2行目以降を下に表示するのではなく、上に積み上げる形で表示します。
[13/11/14 追記]
flex-wrapプロパティは実装状況がブラウザによって大きく異なります。
まず旧仕様であるbox-linesは、仕様には存在するものの実装しているブラウザがありません。
そのため、現時点でbox仕様のみが実装されている、iOS6以前とandroidの標準ブラウザについてはbox-wrapが利用できません。
次にflex-wrapについて、
Firefoxでは、flex仕様が実装されているものの、flex-wrap:wrapには対応していません。(Fx25で確認)
実装が確認できたブラウザとバージョンについては以下のとおりです。
Ch 30 | flex-wrap:wrap |
---|---|
Op 17 | |
iOS 7 | -webkit-flex-wrap:wrap |
ie 10 | -ms-flex-wrap:wrap |
以上は確認できた範囲のため、ここに記載したものより古いバージョンでも動作する可能性があります。
[追記終わり]
flex-flow(表示方向、行制御のショートハンド)
flex directionプロパティとflex-wrapプロパティをまとめて指定できるショートハンドプロパティです。
flexbox仕様から追加されました。
仕様 | プロパティ | 値 |
---|---|---|
box | - | - |
flexbox | flex-flow | <‘flex direction’> || <‘flex-wrap’> |
flex |
対象:flexコンテナ
order(表示順)
flexアイテムの並び順を指定します。
仕様 | プロパティ | 値 |
---|---|---|
box | box-ordinal-group | 整数(自然数のみ) 初期値:1 |
flexbox | flex-order | 実数 初期値:0 |
flex | order | 整数 初期値:0 |
対象:flexアイテム
HTML上に記載された順番を無視して、指定された整数の昇順に表示されます。
同じ数値が指定されていた場合は、HTMLの記載順に従います。
また、整数には負の数も利用できます。
特定の要素だけ一番最初に表示したいケースでは、プロパティの初期値より小さい-1などを指定することで、一番最初に表示することが可能です。
※box-ordinal-groupの仕様では、指定できる値について初期値が1の自然数と定義されており、0と負の数を指定しても無視されます。
一番最初に表示したい要素がある場合は、一旦flexアイテム全体に2を指定してから、最初に表示したい要素に1を指定する、と言った対応が必要になります。
flex(フレキシビリティ)
flexコンテナの幅に対して、flexアイテムの合計幅が小さかったり、大きかったりすると、flexコンテナに余白ができたり、はみ出したりしてしまいます。
そういった場合に、フレキシビリティの指定をすることで、flexアイテムの幅を伸ばして余白を埋めたり、幅を縮めてflexコンテナに収めることがことができるようになります。
※以降、幅を伸ばして余白を埋める挙動を拡幅、幅を縮めてflexコンテナに収める挙動を減幅、と呼びます。
複数のflexアイテムにこの伸縮処理が指定されていた場合は、指定された値の比率に応じてflexアイテムごとに幅が分配され、処理されます。
すべてのflexアイテムに同じ比率が指定されていた場合は、flexコンテナの幅に応じてすべてのアイテムが均等に伸縮します。
仕様 | プロパティ | 値 |
---|---|---|
box | box-flex | 実数(負の数は無効)初期値:0.0 |
box-flex-group | 整数 初期値:1 | |
flexbox | flex | [ [ |
flex | flex | none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]初期値:各プロパティの初期値 |
flex-grow | 実数(負の数は無効、ショートハンドで省略された場合:1)初期値:0 | |
flex-shrink | 実数(負の数は無効、ショートハンドで省略された場合:1)初期値:1 | |
flex-basis | widthプロパティと同じ 初期値:auto |
対象:flexアイテムbox-flexプロパティは、flexbox仕様以降はflexプロパティに名前が変更されました。flexプロパティは、flexbox仕様とflex仕様の間で挙動に大きな違いはありませんが、flexbox仕様で指定できる3つの値(
box仕様
box-flexプロパティ
flexアイテムの拡幅/減幅の比率を指定します。値が「1」以上のflexアイテムがある場合、そのアイテムに対して拡幅/減幅の分配が行われます。「3」と「1」のflexアイテムがある場合は、3:1で分配されます。「5」のflexアイテムが2つある場合は、5:5で分配されるため、等分になります。box-flexプロパティで、拡幅/減幅の両方の分配を指定するため、どちら一方を指定することはできません。(flexbox仕様からは、どちらか一方の指定が可能になります)「0.0」のflexアイテムは拡幅/減幅ともに行われず、flexアイテム自体の幅で表示されます。初期値は「0.0」なので、未指定の場合も拡幅/減幅ともに行われません。
box-flex-groupプロパティ
拡幅/減幅が行われる順番を指定します。通常では全ての余白が埋まるように分配されますが、flexアイテムにmax-widthプロパティが指定されていると余白が残ることがあります。(分配によってwidthが伸びる場合でも、max-widthの値より大きくなることはないため)その場合に「2」以上が指定されたグループに処理が引き継がれ、昇順で順次処理さます。このプロパティは、flexbox仕様以降は廃止されました。
flexbox仕様/flex仕様
flexプロパティ
flexbox仕様では、flexプロパティには「positive flexibility(
指定可能な3つの値
positive flexibility / flex-growプロパティ
flexコンテナの幅に対して、flexアイテムが拡幅する場合の比率を指定します。この比率は、box-flexと同様アイテム間の相対的な数値です。
negative flexibility / flex-shrinkプロパティ
flexコンテナの幅に対して、flexアイテムが減幅する場合比率を指定します。この比率は、box-flexと同様アイテム間の相対的な数値です。
preferred size / flex-basisプロパティ
flex時のflexアイテムの幅です。初期値はautoです。widthプロパティと同様に単位付きの数値(pxや%)とautoが指定可能です。flexアイテムに指定されているwidthの値は分配によって無視されるため、幅を固定したい場合はpreferred sizeを指定します。
noneを指定した場合
拡幅/減幅のどちらの行われず、flexアイテム自体の幅で表示されます。「0 0 auto」を指定した場合、noneと同じ挙動となります。
flexプロパティが未指定の場合
box仕様では、box-flexプロパティが未指定の場合拡幅/減幅ともに行われません。flexbox仕様ではbox仕様と同じく、初期値が「none」のため拡幅/減幅ともに行われません。flex仕様では、初期値は「0 1 auto」となるため、拡幅は行われませんが、減幅は行われます。
flexプロパティで一部値を省略した場合
flexプロパティで、positive flexibility(flex-growプロパティ)、negative flexibility(flex-shrinkプロパティ)を省略して設定する場合、仕様によって取る値が変わります。width/heightのように省略した値は設定した値からコピーされるのではなく、各仕様であらかじめ決められている値が設定されるため、注意が必要です。
flexbox仕様 | flex仕様 | |
---|---|---|
未指定 | 固定(flex:0 0 auto) | 減幅のみ(flex:0 1 auto) |
flex:auto; | 拡幅のみ(flex:1 0 auto) | 減幅/拡幅(flex:1 1 auto) |
flex:2 auto; | 拡幅のみ(flex:2 0 auto) | 減幅/拡幅(flex:2 1 auto) |
flex:2 2 auto; | 減幅/拡幅(flex:2 2 auto) | 減幅/拡幅(f/wlex:2 2 auto) |
box仕様では減幅のみ/拡幅のみの指定はできない点も合わせると、後方互換を考える場合は値を省略せず全て記載したほうがよいでしょう。
justify-content、align-items、align-self、align-content(寄せ)
flexアイテムの縦横方向の寄せを指定するために、次の4つのプロパティが用意されています。
- justify-contentプロパティ(flexアイテムの横方向の寄せ)
- align-itemsプロパティ(flexアイテムの縦方向の寄せ)
- align-selfプロパティ(flexアイテムの縦方向の寄せ・flexアイテム単体)
- align-contentプロパティ(flex行の縦方向の寄せ)
justify-content
flexコンテナに指定することで、flexアイテムの横方向の寄せを指定します。
仕様 | プロパティ | 値 |
---|---|---|
box | box-pack | start | end | center | justify |
flexbox | flex-pack | start | end | center | justify | distribute |
flex | justify-content | flex-start | flex-end | center | space-between | space-around |
対象:flexコンテナ
「-webkit-box-pack」プロパティについて
webkitでは、flexコンテナよりもflexアイテムが大きい場合のみ、-webkit-box-packの指定を無視して常に左寄せになるようです。
align-items、align-self
どちらのプロパティも、flex行に対してのflexアイテムの縦方向の寄せを指定します。align-itemsプロパティは、flexコンテナに指定し、そのコンテナの中すべてのflexアイテムに対して寄せを指定します。align-selfプロパティは、flexアイテムに指定し、指定したflexアイテムのみの寄せを指定します。align-selfプロパティはflexbox仕様から追加されました。
align-items
仕様 | プロパティ | 値 |
---|---|---|
box | box-align | start | end | center | baseline | stretch |
flexbox | flex-align | start | end | center | baseline | stretch |
flex | align-items | flex-start | flex-end | center | baseline | stretch |
対象:flexコンテナ
align-self
仕様 | プロパティ | 値 |
---|---|---|
box | - | - |
flexbox | flex-item-align | auto | start | end | center | baseline | stretch |
flex | align-self | auto | flex-start | flex-end | center | baseline | stretch |
対象:flexアイテム
align-content
flexコンテナに指定することで、flexコンテナに対してのflex行の縦方向の寄せを指定します。このプロパティはflexbox仕様から追加されました。
仕様 | プロパティ | 値 |
---|---|---|
box | - | - |
flexbox | flex-line-pack | start | end | center | justify | distribute | stretch |
flex | align-content | flex-start | flex-end | center | space-between | space-around | stretch |
対象:flexコンテナ
おわりに
flexboxの仕様をまとめて見てきましたがいかがでしたでしょうか。ゲンナリしていただけましたでしょうか。ちなみに全てのベンダープリフィクスをつけた状態で、上下左右中央レイアウトをやろうとすると以下のようになります。
.flexCont{
display:-webkit-box;
display:-moz-box;
display:-ms-flexbox;
display:-webkit-flex;
display:flex;
-webkit-box-pack:center;
-moz-box-pack:center;
-ms-flex-pack:center;
-webkit-justify-content:center;
justify-content:center;
-webkit-box-align:center;
-moz-box-align:center;
-ms-flex-align:center;
-webkit-align-items:center;
align-items:center;
}
最高っにハイッてやつですね。