どうも、くーへいです。
今回は「レスポンシブデザイン」での使用が想定される、「フレキシブルボックス」についてまとめてみたいと思います。
なお、本記事は「CSS Flexible Box Layout Module Level 1」の2014年5月22日付けの編集者草案(Editor’s Draft)を基に作成しています。
また、「CSS Flexible Box Layout Module Level 1」は未だに策定中であり、現在は2014 年3月25日付の最終草案(Last Call Working Draft)が最新仕様です。
2014年5月22日付けの編集者草案は、2014 年3月25日付の最終草案に微修正を加えたものです。
最初にブラウザの対応状況について注意点
「フレキシブルボックス」で検索すると、いくつかの素晴らしい記事が出てきますが、中には古い記事が多く含まれています。
「display:box」や「display:flexbox」という書き方は、W3Cの仕様上では古いものになります。
ブラウザによっては、ベンダープレフィックス(-mozや-webkitや-ms)によってサポートされる記述もありますが、ブラウザごとのサポート状況は注意が必要です。
PC-Chrome
バージョン4~20までは「display:-webkit-box」
21~28までは「display:-webkit-flex」
28以降は「display:flex」
PC-Firefox
バージョン2~21までは「display:-moz-box」
22以降は「display:flex」
PC-InternetExplorer
バージョン9までは「未対応」
10は「display:-ms-flexbox」
11は「display:flex」
PC-Safari
バージョン3.1~6.0までは「display:-webkit-box」
6.1以降は「display:-webkit-flex」
Android-標準ブラウザ
バージョン2.1~4.3までは「display:-webkit-box」
4.4では「display:flex」
Android-Chrome
バージョン35?「display:flex」
iOS-Safari
バージョン3.2~6.1までは「display:-webkit-box」
7.0では「display:-webkit-flex」
このように状況を見てみると、最新のブラウザではiOSのSafariを除いて「display:flex」に対応していますが、旧ブラウザでは「display:-webkit-box」での対応が多いでしょうか。
「フレキシブルボックス」とは?
通常のCSSでは、ブロック要素は下に連なり、インライン要素は横に連なる性質を持っていますよね。
このうち、ブロック要素を横に連ねるためには、
フロートを使用する
ul li { float:left; }
テーブルレイアウトを使用する
ul{ display:table; } ul li{ display:table-cell; }
のような方法があります。
これらにもう1つ方法が加わる形で、
フレキシブルレイアウト
ul{ display:flex; }
という書き方で実現できます。
その他にも、自動で伸縮したり、ボックスの順序を入れ替えたりと今までできなかったことができるようになります。
「フレキシブルボックス」で出来ること
「フレキシブルボックス」で出来ることは以下の通りです。
- 要素の配置方向を自由に決められる
- 要素の配置順序を自由に決められる
- 要素の折り返し方法を設定できる
- 要素のサイズを伸縮自在にできる(余った空間すべてをある要素に割り当てる、など)
- 要素を整列させられる
などなどです。
「フレキシブルボックス」のプロパティ解説
ここからは「フレキシブルボックス」のプロパティを順番に解説していきたいと思います。
「display:flex」、「display:inline-flex」
「display:flex」はブロックレベルのflexコンテナボックスを、「display:inline-flex」はインラインレベルのflexコンテナボックスを生成します。
以下はそれぞれを指定した例です。(以下、図で例示したものは、Chromeバージョン35で実行したものです)
HTML(抜粋)
<section class="block color"> <h1>通常のブロックレイアウト</h1> <ul class="display"> <li>1</li> <li>2</li> <li>3</li> </ul> </section> <section class="inlineFlex color"> <h1>フレキシブルボックスのインラインレイアウト</h1> <ul class="display"> <li>1</li> <li>2</li> <li>3</li> </ul> </section> <section class="blockFlex color"> <h1>フレキシブルボックスのブロックレイアウト</h1> <ul class="display"> <li>1</li> <li>2</li> <li>3</li> </ul> </section>
「通常のブロックレイアウト」のCSS(抜粋)
.block .display{ display:block; }
「フレキシブルボックスのインラインレイアウト」のCSS(抜粋)
.inlineFlex .display{ display:inline-flex; }
「フレキシブルボックスのブロックレイアウト」のCSS(抜粋)
.blockFlex .display{ display:flex; }
通常のブロックレイアウトとは異なるのがわかります。
ちなみに、上の画像の例だと、「1」「2」「3」という数字が入った要素の親の要素(displayクラスのdiv要素)を「flexコンテナ」、数字の要素自体(displayクラスのdiv要素直下のp要素)を「flexアイテム」と呼びます。
「display:flex」と「display:inline-flex」の違いが出ていませんが、併用するプロパティによって異なってきますので、各項をチェックしてください。
なお、「フレキシブルボックス」を使用すると、以下の制約を受けます。
- 「column-* プロパティ」は、使用できない。(CSS3のプロパティ)
- 「float」、「clear」は、使用できない。
- 「vertical-align」は、使用できない。
- 「::first-line」、「::first-letter」疑似要素は、使用できない。
「flex-direction」
※「display:box」では「box-orient」と「box-direction」に分かれています。「box-orient」で方向(horizontal | vertical | inline-axis | block-axis)を決め、「box-direction」で順序(normal | reverse)を決めます。
「flexコンテナ」の主軸の方向を決めます。「flexアイテム」は、主軸の方向に沿って配置されていきます。
「flexコンテナ」に適用
初期値:row
row
文字を入力するのと同じ方向に配置されていきます。日本語ですと(というかほとんどの言語がそうなのですが)左から右ですね。
row-reverse
rowの逆順になります。
column
「display:block」と同じような並びになります。
column-reverse
columnの逆順になります。
※フレキシブルボックス自体がインラインレイアウトかブロックレイアウトかによって表現が変わってきますので、下記の画像を確認してください。
「flex-wrap」
※「display:box」では同等のプロパティが存在しません。
「flexアイテム」の折り返しについて、設定します。
「flexコンテナ」に適用
初期値:nowrap
nowrap
「flexアイテム」が折り返しせず、「flexコンテナ」を突き抜けてゆく。
wrap
「flexアイテム」が折り返され、複数行になる。
wrap-reverse
wrapの順序逆バージョン
「flex-flow」
※「display:box」では同等のプロパティが存在しません。
「flex-flow」は、「flex-direction」と「flex-wrap」を同時に指定できます。
「background」が、「background-image」や「background-repeat」などを同時に指定できるのと感覚が似ているでしょうか。
flex-flow:row-reverse wrap-reverse;
上記のように指定します。
flex-flow:<flex-directionの値> <flex-wrapの値>;
と、いうように指定します。
「flexコンテナ」に適用
初期値:各プロパティに準じる
「order」
※「display:box」の場合は使用できません。「box-ordinal-group」を使用してください。
「flexアイテム」は、通常はHTMLに記述された順序で表示されていきますが、orderプロパティを使用することで、この順序を変更できます。
初期値は「0」になっているので、(他の「flexアイテム」が初期値のままであれば)ある「flexアイテム」の「order」を「1」とすると一番最後に表示されますし、「-1」とすると一番最初に表示されることになります。
なお、「order」はあくまで見え方の変更のみなので、読み上げを行う場合には「order」の値は無視されるでしょうし、検索エンジンでもHTMLに書かれた順序が読み込まれます。
「レスポンシブデザイン」ではこのプロパティは大いに活躍するでしょう。
「flexアイテム」、もしくは「flexコンテナ」の子で絶対配置されているものに適用
初期値:0
「flex-grow」、「flex-shrink」、「flex-basis」について
タイトルにもあげた3つのプロパティは、「flexアイテム」が「flexコンテナ」の幅を埋め尽くすように自動で幅を調整するためのプロパティです。
それぞれの違いについては、以下の通り。
「flex-grow」
※「display:flexbox」の場合は使用できません。「flex」を使用してください。
※「display:box」の場合は「box-flex」になります。
「flex-grow」プロパティは、伸長係数を設定します。数字で入力します。
全ての「flexアイテム」に「flex-grow」を「1」、1つの「flexアイテム」に「flex-grow」を「2」と設定した場合、その「flexアイテム」は他の2倍の大きさになります。
「flexアイテム」に適用
初期値:0
負の値は使用不可
「flex-shrink」
※「display:flexbox」の場合は使用できません。「flex」を使用してください。
※「display:box」の場合は「box-flex-group」になります。
「flex-shrink」プロパティは、縮短係数を設定します。数字で入力します。
「flex-grow」とは反対に、数字が大きいほど幅が小さくなっていきます。
なお、「flex-shrink」は「flex-wrap:nowrap」でないと、効果はありません。また、「flex-shrink」のみで自動的に空白を埋めることもありません。
「flexアイテム」に適用
初期値:1
負の値は使用不可
「flex-basis」
※「display:flexbox」の場合は使用できません。「flex」を使用してください。
※「display:box」では同等のプロパティが存在しません。
「flex-basis」は、「width」や「height」と同じような値が設定できます。
動きも「width」や「height」と大差ありませんが、大きく異なるのは「flex-direction」で「row」や「row-reverse」のときは「flex-basis」は横幅を、「flex-direction」で「column」や「column-reverse」のときは高さに「flex-basis」の値が使用される点です。
「flexアイテム」に適用
初期値:auto
負の値は使用不可、パーセント等使用可
「flex」
※「display:box」では同等のプロパティが存在しません。
「flex」は、「flex-grow」「flex-shrink」「flex-basis」の値を同時に指定できます。
「flex:<flex-growの値> <flex-shrinkの値> <flex-basisの値>;」と書きます。
「none」に設定すると「0 0 auto」、「auto」に設定すると「1 1 auto」、「initial」に設定すると「0 1 auto」と設定される。
「justify-content」
※「display:flexbox」の場合は「flex-pack」になります。
※「display:box」の場合は「box-pack」になります。
「justify-content」は、「flexアイテム」を整列します。
「justify-content」では、1つのライン上における「空間」の配置方法を決定するものと考えるとわかりやすいでしょうか。
flex-start
※「display:flexbox」、「display:box」の場合は「start」になります。
「flexアイテム」はラインの始端に向けて収納されます。始端から間隔なしに配置され、最後に余った空間が置かれます。
flex-end
※「display:flexbox」、「display:box」の場合は「end」になります。
「flexアイテム」はラインの終端に向けて収納されます。終端から間隔なしに配置され、始端に余った空間が置かれます。(「flexアイテム」の順序が入れ替わるわけではありません。図を参照してください)
center
「flexアイテム」はラインの中央に向けて収納されます。つまり、余った空間を均等に割り、始端と終端に置かれます。(「flexアイテム」の横幅合計が「flexコンテナ」の横幅を上回る場合(余った空間が負の場合)は両方向に等しくoverflowされます。)
space-between
※「display:flexbox」、「display:box」の場合は「justify」になります。
「flexアイテム」はライン内に均等に分布されます。ただし、始端と終端には空間が入りません。「flexアイテム」の横幅合計が「flexコンテナ」の横幅を上回る場合(余った空間が負の場合)、あるいはライン上の「flexアイテム」が 1 個だけの場合、この値の効果は「flex-start」と同一になります。
space-around
※「display:flexbox」の場合は「distribute」になります。
※「display:box」の場合は該当する値がありません。
「flexアイテム」は、両端には半分サイズの空間を伴う様に、ライン内に均等に分布されます。「flexアイテム」の横幅合計が「flexコンテナ」の横幅を上回る場合(余った空間が負の場合)、あるいはライン上の「flexアイテム」が 1 個だけの場合、この値の効果は「center」と同一になります。
ちなみに、「flexアイテム」と「flexアイテム」の間の間隔の半分の大きさが始端と終端に置かれます。
イメージとしては、各「flexアイテム」の両端に間隔が置かれるようなイメージでしょうか。
※画像は「CSS Flexible Box Layout Module Level 1」より
「align-items」、「align-self」
※「display:flexbox」の場合は「align-items」→「flex-align」、「align-self」→「flex-item-align」になります。
※「display:box」の場合は「box-align」のみになります。
「flexアイテム」は、「justify-content」と同様に縦方向も整列できます(「flex-direction」の値によっては横方向になったりもします)。
「align-items」は、「flexコンテナ」に指定し、「匿名flexアイテム」も含め「flexコンテナ」の「flexアイテム」すべてに対する既定の整列を設定します。
「align-self」は、「flexアイテム」に指定し、この既定の整列を、個々の「flexアイテム」について上書きできるようにします。(「匿名flexアイテム」に対する「align-self」は、それらに結び付けられている「flexコンテナ」上の「align-items」の値に常に合致する。)
「flexアイテム」の縦方向のマージン(「flex-direction」の値によっては横方向になったりもします)がいずれも「auto」である場合、「align-self」は効果がありません。
「align-self」の「auto」は、要素が親を持つならば、その親の「align-items」の値、持たないならば「stretch」に算出されます。
下記は「flex-direction」等が初期値である場合です。
flex-start
※「display:flexbox」、「display:box」の場合は「start」になります。
「flexアイテム」は上に配置されます。
flex-end
※「display:flexbox」、「display:box」の場合は「end」になります。
「flexアイテム」は下に配置されます。
center
「flexアイテム」は上下中央寄せになります。
baseline
ベースラインを揃えるようにして配置されます。
stretch
高さに取り決めがない「flexアイテム」は、「flexコンテナ」の高さまで広がります。ただし、「max-height」などに制約されます。
※画像は「CSS Flexible Box Layout Module Level 1」より
「align-content」
※「display:flexbox」の場合は「flex-line-pack」になります。
※「display:box」の場合は該当するプロパティがありません。
「align-content」は、「align-items」の複数ラインバージョンとも言えるでしょうか。
配置の仕方としては、「justify-content」に似ています。
当然ですが、このプロパティは「flexコンテナ」が単独のラインのみからなるときには効果を持ちません。
flex-start
※「display:flexbox」の場合は「start」になります。
一連のラインは、「flexコンテナ」の始端に向けて収納されます。
flex-end
※「display:flexbox」の場合は「end」になります。
一連のラインは、「flexコンテナ」の終端に向けて収納されます。
center
一連のラインは、「flexコンテナ」の中央に向けて収納されます。
space-between
※「display:flexbox」の場合は「justify」になります。
一連のラインは、「flexコンテナ」の中で均等に分布されます。始端と終端には空間は持たれません。
space-around
※「display:flexbox」の場合は「distribute」になります。
一連のラインは、「flexコンテナ」の中で均等に分布されます。始端と終端にはラインとラインの空間の半分の空間が持たれます。
stretch
空間がないようにラインの高さ(「flex-direction」の値によっては横幅になったりもします)を伸ばします。
※画像は「CSS Flexible Box Layout Module Level 1」より
まとめ
ここまでフレキシブルボックスについてまとめてみましたが、いかがでしたでしょうか。
モダンブラウザでしか利用できないことは残念ですが、これでレイアウトの幅が大きく広がりますね!
本文中にも書きましたが、「レスポンシブデザイン」との親和性が高いので、下記記事もあわせてどうぞ。
参考:”レスポンシブなサイトをつくりたい!実装方法はじめの一歩“