使い始めたら手放せないフレキシブルボックスレイアウトモジュールについて熱く語ります。
注)
これは6年前に社内向けレポートか何かで書いたやつだと思います…(うろ覚え)
今でも通用する内容だったのでドライブにあった原稿を転載しました。
内容が古いところは加筆修正してます。
フレキシブルボックスレイアウト?とは?
5つめの新しいレイアウト方法です。
今は知ってないと恥ずかしいレベルにメジャーとなったレイアウト方法です。
CSSで何かの要素を配置しようとしたとき、選択可能な手段は4つありました。
- ブロックレイアウト
—— 文書をレイアウトする為に設計されたもの。 - インラインレイアウト
—— テキストをレイアウトする為に設計されたもの。 - テーブルレイアウト
—— 2Dデータを表形式でレイアウトする為に設計されたもの。 - ポジショニングレイアウト
—— 要素に授ける自由の翼。
Web制作経験がある人ならこの4つ全て使ったことがあると思いますが、同時にこの4つだけでは痒い所に手が届かない事例に遭遇した事があるんじゃないでしょうか。
Flexレイアウトはユーザー インターフェイス設計のために最適化されているので、上記4つ+ノウハウ+JSでやっつけていたようなレイアウトを驚くほど簡単に作ることができます。
なにができるの?
フレキシブルボックスレイアウトは子要素を任意の方向に並べる事が得意です。
並べた要素の順番を入れ替えることもプロパティの指定1つで行えます。
仕様の変遷と対応ブラウザ
とてつもなく便利なモジュールですが、残念な歴史が1つ。
それはブラウザによって対応する仕様とシンタックスが違っていたということです。
W3C Working Draft, 23 July 2009
http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/
現状一番多くのブラウザがサポートしている仕様。
この仕様をサポートしたブラウザが登場するようになったことで、フレキシブルボックスというものが広く認知されるようになった。
古いPC版ブラウザとスマートフォン版ブラウザ相手ならこの仕様。2019年現在この仕様の端末は販売されていません。
W3C Working Draft, 22 March 2012
http://www.w3.org/TR/2012/WD-css3-flexbox-20120322/
2011〜2012年春仕様。box-だったところがflex-になった。
丁度同時期に開発中だったのか、何故かIE10だけがこの仕様に準拠している。
_人人人人人人人人人人_
> IE10だけこの仕様 <
 ̄Y^YY^YYYY^YY^Y ̄
W3C Candidate Recommendation, 18 September 2012
http://www.w3.org/TR/css3-flexbox/
勧告候補。PC版ブラウザの最新版(IE10以外)は概ね対応してきている。
現在はこれ。あの頃夢見た世界がやっと…
シンタックスで見る仕様の違い
親要素(黒い枠)の中に3つの子要素を均等配置するケースについて、各仕様に準じた書き方をすると以下のようになります。
※ベンダープレフィックスは全て省略しています。
W3C Working Draft, 23 July 2009 の場合
div { display: box; box-pack: justify; box-align: center; box-orient: horizontal; }
W3C Working Draft, 22 March 2012 の場合
div { display: flexbox; flex-pack: justify; flex-align: center; flex-direction: row; }
W3C Candidate Recommendation, 18 September 2012の場合
div { display: flex; justify-content: space-between; align-items: center; flex-flow: row; }
これを書いている現時点(2013/9)ではW3C Working Draft, 23 July 2009の仕様で書いておけば対応するPC・スマートフォン両方のブラウザをカバーすることができます。
勧告版仕様を使いたい場合は、
PC→勧告仕様
IE10→2012仕様
スマホ・旧PC→2009仕様
を使い分けることになります。
2019年現在は勧告仕様で概ねオッケーですが、ベンダープレフィックスの有無などで脚を引っ張られる事があります。
サポート状況はブラウザによって異なるので、対応状況は随時Caniuse.com等で確認してください。
用語の図解
どちらの場合も基本的にレイアウトの方向が主軸となります。
- Flexコンテナ
flexアイテムを含む親要素のこと。 - Flexアイテム
flexコンテナの子要素。flexコンテナに直接テキストが入っている場合は、無名のflexアイテムに包まれる。 - 主軸(main axis) ・交差軸(cross axis)
レイアウト時に基準となる軸。
交差軸は、横方向レイアウトの場合(上図)は縦軸だが、縦方向レイアウトの場合は横軸になる。
レイアウトの方向によって主軸が変わるので、操作するプロパティも変わります。 - main start/main end
Flexアイテムは主軸を基準としてmain startからmain end方向へレイアウトされる。縦方向レイアウトの場合はmain startが上、main endが下になる。 - cross start/cross end
マルチラインレイアウトの場合、cross startからcross endに向けてFlexアイテムが配置される。
レイアウトの方向が横の場合
レイアウトの方向が縦の場合
プロパティの説明とサンプル
display:flex/inline-flex
flexコンテナの生成はdisplay
プロパティの値にflex
もしくはinline-flex
を指定することです。
指定する要素はブロックレベル・インラインレベルを問いません。
display:flex
のflexコンテナはブロックレベル、display:inline-flex
のflexコンテナはインラインレベルになります。
元がブロックレベルの要素であっても、display:inline-flex
を指定するとdisplay:inline-block
を指定したのと同じような挙動になります。
それとは逆に、要素にdisplay:inline-flex
とfloat
あるいはposition:absolute
が指定してある場合、display
の算出値はflexになります。
See the Pen
Flexible Box Layout Module sample by Tenderfeel (@Tenderfeel)
on CodePen.
Flexコンテナ内で適用されないプロパティ
ブロックレイアウト前提で設計されたプロパティのうち、いくつか使用できないものがあります。
- Flexコンテナに対するすべての column- (マルチカラムレイアウトモジュール)プロパティ
- Flexアイテムに対する float と clear プロパティ
- Flexアイテムに対する vertical-alignプロパティ
flex-direction
指定したFlexコンテナー内にあるFlexアイテムのレイアウト方向を設定するプロパティ。
レイアウトの起点はmain startですが、reverseを付けると逆転してmain endになります。
- row —— 横方向(デフォルト)用語にある図の1つ目
- row-reverse —— 横方向(main endが起点)
- column —— 縦方向。用語にある図の2つ目
- column-reverse —— 縦方向(main endが起点)
See the Pen
CSS flex-direction sample by Tenderfeel (@Tenderfeel)
on CodePen.
flex-wrap
FlexアイテムがFlexコンテナの末端に達したとき、自動で折り返すか否かを決める。レイアウトの基準になるのは交差軸で、プロパティの役割はwhite-space
に近い。
- nowrap —— Flexコンテナ内を1行でレイアウトする。FlexアイテムはFlexコンテナに収まるサイズに拡大・縮小する
- wrap —— Flexコンテナ内を複数行にレイアウトする。Flexアイテムは末尾のものから順に新しい行へ配置される
- wrap-reverse —— 挙動はwrapと同じだが、折り返しの向きが逆転する。
See the Pen
CSS flex-wrap sample by Tenderfeel (@Tenderfeel)
on CodePen.
flex-flow
flex-direction
とflex-wrap
を同時に指定するショートハンドプロパティ。
flex-directionの値の後、スペースで区切ってflex-wrapの値を記述する。
See the Pen
CSS flex-flow demo by Tenderfeel (@Tenderfeel)
on CodePen.
order
Flexアイテムに対して並び順を指定するプロパティ。値は数値で初期値は0。
マイナスの値を指定した場合は前方に、0より大きい数値を指定した場合は後方に配置される。
See the Pen
CSS flexible box order demo by Tenderfeel (@Tenderfeel)
on CodePen.
justify-content
FlexアイテムをFlexコンテナの主軸に沿って整列するプロパティ。space- 系が神過ぎる。
space-evenly
は登場が新しく、IE11やAndroid4系などが未対応です。
- flex-start —— main startを起点に詰めて配置(初期値)
- flex-end —— main end を起点に詰めて配置
- center —— 中央に配置
- space-between —— 最初と最後のflexアイテムをmain startとmain end寄りに配置。余ったスペースで残りのflexアイテムを均等に配置
- space-around —— 全てのflexアイテムを均等に配置し、各アイテムの両側に半分の大きさの間隔を置く
- space-evenly —— 全てのflexアイテムを均等に配置し、各アイテムの周りに同じ大きさの間隔を置く
See the Pen
CSS justify-content sample by Tenderfeel (@Tenderfeel)
on CodePen.
align-items/align-self
交差軸に沿って指定するプロパティ。align-items
はFlexコンテナに、align-self
はFlexアイテムに指定するプロパティです。
- flex-start —— cross startを起点に詰めて配置
- flex-end —— cross endを起点に詰めて配置
- center —— 中央に配置
- baseline —— ベースラインが一直線になるように配置
- stretch —— 同じ列にあるFlexアイテムが全て同じ高さになるように配置(初期値)
- auto —— align-selfのみ指定可能。親要素のalign-items値を計算する(初期値)
See the Pen
CSS align-items sample by Tenderfeel (@Tenderfeel)
on CodePen.
align-content
Flexコンテナがマルチラインである場合に、交差軸に沿って列の整列を指定するプロパティ。1行しか無い場合は影響しません。
- flex-start —— cross startを起点に詰めて配置
- flex-end —— cross endを起点に詰めて配置
- center —— 中央に配置
- space-between —— 最初と最後の列をcross startとcross end寄りに配置。余ったスペースで残りの列を均等に配置
- space-around —— 全ての列を均等に配置
- stretch —— 全ての列が同じ高さになるよう配置(初期値)
See the Pen
CSS align-content sample by Tenderfeel (@Tenderfeel)
on CodePen.
flex
このプロパティは flex-grow
、flex-shrink
、flex-basis
を一括指定するショートハンドで、Flexアイテムの幅をどのように扱うかを指定することが出来ます。
指定先はFlexアイテムです。
値の順番は次の通りです。
flex: <flex-grow> <flex-shrink> <flex-basis>;
flex-growとflex-shrinkは省略できます。省略された場合はどちらも1になります。
flex-basisを省略した場合は0pxが初期値になります。
初期値はこのようになっています。
flex: 1 1 0px;
flex-grow —— 親要素が大きすぎたときにFlexアイテムに振り分ける余白の割合
flex-shrink —— 親要素のサイズが不足しているときFlexアイテムをどれだけ縮小するか
flex-basis —— Flexアイテムのサイズを指定する
次のサンプルはflex-grow、flex-shrink、flex-basisの値をそれぞれ変えてみたものです。
See the Pen
flex-grow/flex-shrink demo by Tenderfeel (@Tenderfeel)
on CodePen.
FlexItem1 → 拡大も縮小もしない。ウィンドウサイズを変えても150pxのまま変わらない。
FlexItem2 → 拡大時の割合を2、縮小時は1とする。ウィンドウサイズに比例して拡大縮小する。拡大するときはFlexItem3よりも割合が大きい。
FlexItem3 → 拡大はするが縮小はしない。幅150pxより小さくならないが、ウィンドウサイズが大きければ広がる。
flex-basis
はflex-shrink
の値が0である場合、調整無視して指定されたサイズで描画するため親要素のサイズが足りなくなった場合に他のFlexアイテムがはみ出します。
上のサンプルでは一番最後にあるFlexItem2用のflexプロパティの値を 2 0 300px
に変更すれば確認できます。
次のサンプルはflex-basis
でflexアイテムを操作してみたものです。
See the Pen
CSS flex-basis sample by Tenderfeel (@Tenderfeel)
on CodePen.
.title → flexで100%指定。後続の.thumbと.descriptionを2列目に押しやる
.thumb → widthとheightだけ指定。
.description → flexで1を指定。thumb配置後に余った所を全部占領させる
Flexアイテムの挙動について
position:absoluteを指定した場合
Flexレイアウトはされず、いつも通りの挙動です。が、top
とbottom
、left
とright
がauto
である場合static
と同じ挙動になるので、margin:auto
でセンタリングする手法は使えません。
See the Pen
flexible box item absolute demo by Tenderfeel (@Tenderfeel)
on CodePen.
visibility:collapseを指定した場合
Flexアイテムにvisibility:collapse
を指定した場合、table-row
やtable-cell
と同じ効果になります。collapseに関してはブラウザの挙動がまちまちなので、その対応状況に引きずられてしまうようです。
See the Pen
Flexiblebox and visibility:collapse sample by Tenderfeel (@Tenderfeel)
on CodePen.
おまけ
あるあるリストスタイル
左に配置したサムネイルにコンテンツの背景が回り込んだり回り込まなかったりするリストのサンプル。
See the Pen
Flexible box layout sample by Tenderfeel (@Tenderfeel)
on CodePen.
参考文献
- http://www.w3.org/TR/css3-flexbox/#flex
- https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Flexible_boxes
- http://hyper-text.org/archives/2013/07/css_flexible_box.shtml