フレックスボックス
スマートフォン、タブレット、ラップトップ、PC のモニターなどの様々なデバイス上で、 さらに様々なサイズの画面でも適切にウェブサイトが表示されるようにするのが、 レスポンシブという考え方ですね。
レスポンシブなウェブサイトを実装するためのひとつの方法として、CSS では Flexbox (フレックスボックス) が導入されました。
ここでは、フレックスボックスの考え方について概要を説明したいと思います。
フレックスボックスとは?
基本的にはフレックスボックスというのは、画面のサイズに合わせて「柔軟に、いい塩梅に、 DOM 要素が伸び縮みしてほしい」 とか、「レイアウトが変わってほしい」という希望に応えるものです。
空いた部分を埋めるように伸縮させたり、あるいは伸縮しないように指定することが可能です。
コンテナと子要素
フレックスボックスは子要素のコンテナ (入れ物) となります。
コンテナの属性では、それに含まれる子要素をどのように配置するか等を指定します。
子要素の属性としては、どのように伸縮するか、子要素間でどういう順序で並ぶかなどを指定します。
軸の向きと数
フレックスボックスのコンテナでは、軸 (axis) というのを考えます。 「主軸」を明示的に指定して、主軸に対する配置と主軸の直交方向との関連などを考えます。
縦方向を主軸にするのは column (カラム、列)、横方向を主軸とするのは row (ロー、行) といいます。
主軸方向の軸を複数許可することを wrap (ラップ、折返し)、軸を 1 本だけに維持することを nowrap といいます。
CSS の指定方法
私の考えではフレックスボックス系の CSS プロパティ名は、かなり分かりにくい (直感と違う) 名前がついているので要注意です。
主軸の向きと数は CSS の flex-flow で指定します。
主軸の向きは row と column、 主軸を1本にする場合は nowrap、複数本を許す場合は wrap とします。
行方向、複数軸とするには次のように指定します。
flex-flow: row wrap;
ちなみに、flex-flow は flex-direction プロパティと flex-wrap プロパティの簡略形式 (shorthand) です。
このページで CSS の書き方は全ては網羅できないので、主な書き方として考えてください。
リファレンスの完全版としては W3C のウェブサイトをベースに考えつつ、各ブラウザの仕様を確認するといいです。
配置の指定
まずはコンテナに含まれる子要素が伸縮しないことを前提に、要素の配置指定方法を説明します。
justify-content ~ 主軸方向の配置指定
justify-content CSS プロパティで、 コンテナの主軸方向で、子要素をどのように配置するか指定します。
子要素が伸縮しない場合、主軸が row のコンテナ内では、 justify-content で次のように配置が変わります。
子要素が伸縮しないというのは、後で説明しますが子要素の flex-grow プロパティが 0 の場合です。このとき、子要素は伸縮しない (形が変わらない) ので、正方形のまま場所だけ変わっています。
上図では子要素は幅 70px で、コンテナの幅は 450px です。子要素が並ぶ場所には余裕があり、伸縮しない場合は上図のように要素間に隙間ができています。
子要素が伸縮する場合 ~ ここで子要素の flex-grow プロパティを全て 1 とすると、隙間を埋めるように子要素が伸長し、次のように表示されます。
どれも同様に表示されてしまい、これではプロパティ設定の違いを理解しにくいので、伸縮する場合は後でまとめて説明します。
align-items と align-self ~ 主軸と直交方向の配置指定
コンテナ内で主軸と直交方向の配置を決めるのは、基本的に子要素の align-self プロパティです。 コンテナの align-items プロパティは子要素の align-self のデフォルト値になります。
子要素が伸縮しない場合、align-self プロパティの違いによって次のように配置が変わります。
主軸が複数の場合
例えば、幅が 100px の子要素が3つあるのに、それを含むコンテナの幅が 200px しかないとします。
このときもし、主軸が 1 本しか許可されない場合、すなわち flex-wrap プロパティの値が nowrap であれば、 子要素はコンテナからはみ出てしまいます。
そこで、要素の配置の折返し (wrap) の出番です。 主軸を複数本を許可 (すなわち、flex-wrap プロパティを wrap) すると、 コンテナからはみ出ないように、子要素が折り返して配置されます。
折り返した子要素も 2 本目、3 本目・・・の主軸を起点に配置されます。
そこで、主軸自体の配置方法を指定する必要がでてきます。
複数本の主軸間の配置を決めるのは align-content プロパティです。 このプロパティは nowrap のとき、もしくは主軸が 1 本しかない場合は何もしません。
次の例では justify-content は flex-start、 align-self ( align-items) は flex-start としています。 このとき align-content プロパティによって、次のように配置が変わります。
さて、ここまでは子要素が伸縮しない場合の配置指定方法をみてきました。
次はいよいよ、子要素の伸縮の設定をします。これによってフレックスボックスがかなり便利なものであることが実感できると思います。
伸縮・順序の指定
フレックスボックスでは子要素を伸縮させることで、とても便利になります。
伸縮の指定
フレックスボックスの子要素が、コンテナのサイズに合わせて文字通りフレキシブルに (柔軟に) 伸縮するには、flex-grow プロパティを 0 より大きな値に設定します。0 の場合は伸縮しません。
flex-grow の数字は、要素の伸長割合を表します。サイズの比率ではありません。
例えば、コンテナの幅が 280px で、子要素 A, B の初期幅がどちらも 80px の場合を考えます。そして A、B の flex-grow 値をそれぞれ 1 と 2 にしたとします。
すると、80px が 2 個で 160px。コンテナが 280px なので、隙間(伸びしろ) が 280 - (80*2) = 120px です。 A と B が伸長することで、この隙間を埋めます。 このときの伸長割合が A、B でそれぞれ 1:2 となります。
120px の隙間のうち 1:2 の割合で A, B が伸長するので、A の伸び幅は 40px、B の伸び幅は 80px です。 よって、元の幅 80px にそれらを足し合わせて、結局、A, B の幅は 120px と 160px になります。
縮小する場合には flex-shrink プロパティで設定します。
最大幅や最小高さなど、サイズの制限値を設ける場合は max-width、min-width、 max-height、min-height プロパティが使えます。
順序の指定
子要素の order プロパティを設定することで、任意の表示順に変更することができます。
<!DOCTYPE html>
<html>
<head>
<title>Flexbox</title>
<style>
* {
box-sizing: border-box;
font-family: sans-serif;
}
.flex-container {
display: flex;
flex-flow: row wrap;
width: 280px;
height: 80px;
}
.flex-container > div {
flex-grow: 1;
font-size: 30px;
text-align: center;
line-height: 80px;
}
</style>
</head>
<body>
<div class="flex-container">
<div style="order:3;background-color:#E1F5FE;">A</div>
<div style="order:1;background-color:#81D4FA;">B</div>
<div style="order:2;background-color:#29B6F6;">C</div>
</div>
</body>
</html>
このように order プロパティを設定することで次のように表示されます。
まとめ:フレックスボックスの使用例
これらを組み合わせると、次の例のように大変柔軟性に富むレイアウトが可能になります。
以上で、フレックスボックスの考え方と基本的な CSS の設定方法について説明しました。