ボックス要素の横並びをCSSで行う場合、従来はfloat
プロパティを使うのが主流でした。しかし、CSS 3の新機能「Flexbox」を使うとfloat
よりも簡潔なコードで、ボックスの豊富なレイアウトが可能です。本記事ではウェブページの作成を通してFlexboxの特徴と使い方について解説します。
この記事で学べること
・flexboxの使い方
・スマートフォンへのレスポンシブ対応
・旧式ブラウザにflexboxを対応させる方法
Flexboxはボックスレイアウト用のCSS 3
Flexboxとは、ボックスのレイアウト方法を定めるCSS 3の機能です。ボックスとは、HTML上の各要素が生成する領域のことです。下図のHTMLコードのウェブページでは、div
要素・h1
要素・p
要素がそれぞれボックスを生成します。
Flexboxでは、ボックスを横ならびにしたり、右寄せ・中央寄せ・左寄せをしたりと、さまざまなレイアウトを少量のコードで実現できます。
大手のプロダクトで使われるFlexbox
Flexboxは、すでに大手のプロダクトで使われ始めています。Twitter社製のUIフレームワーク「Bootstrap 4」では、グリッドレイアウト・カードデザインのレイアウト等の一部のUIで採用されています。ハイブリッドアプリ(Web技術を使って開発するアプリ)作成フレームワーク「Ionic」では、グリッドレイアウト、ボタン、ナビゲーションなど、多くのボックスレイアウトに用いられています。
GoogleのショーケースChrome Experimentsに掲載された、弊社開発の「Particle Develop」でもグリッドレイアウトやタブ、ボタン等にFlexboxを採用しました。
今回作成するウェブページについて
今回はレスポンシブなページのコーディングを例にしてFlexboxの説明します。まずは完成形のページをご覧ください。シンプルなカラムレイアウトをFlexboxを使って実現しています。
Flexboxでのレイアウト方法
まずはヘッダー部分のコーディングです。
HTMLコードは次のとおりです。
<header>
<img src="images/logo.png" alt="">
<ul>
<li><a href="">menu1</a></li>
<li><a href="">menu2</a></li>
<li><a href="">menu3</a></li>
</ul>
</header>
ヘッダー部分のコーディングには、次の3つの過程が必要です。
- ボックスをFlexboxレイアウトとして指定する
- ロゴとメニューを左右に振り分ける
- ヘッダー内を縦方向中央揃えにする
Flexboxレイアウトの指定と2つの軸
ボックスの横並びや縦並びといったFlexboxのレイアウトを指定するとき、ボックスの親要素のスタイルのdisplay
プロパティにflex
を設定します。今回は、header
タグとul
タグです。
header {
display: flex;
}
ul {
display: flex;
}
Flexboxにおけるボックスのレイアウトは、「主軸」と「交差軸」という2つの軸によって決定されます。初期状態では、左から右方向の軸が主軸、上から下方向の軸が交差軸となります。
横方向・縦方向にボックスを並べる
主軸に沿った方向(初期状態で横方向)の並び方はjustify-content
プロパティで設定します。各々の設定値は次の通りです。
flex-start
→ 始端揃え(左揃え、初期値)center
→ 中央揃えflex-end
→ 終端揃え(右揃え)space-between
→ 均等配置(両端ボックスは始端と終端)space-around
→ 均等配置(両端ボックスは始端、終端からボックス間隔の半分の距離)
交差軸に沿った方向(初期状態で縦方向)の並び方はalign-items
プロパティで設定します。各々の設定値は次の通りです。
stretch
→ 親要素と同じ高さに伸びる(初期値)flex-start
→ 始端揃え(上揃え)center
→ 中央揃えflex-end
→ 終端揃え(下揃え)
ヘッダー部分では、ロゴとメニューを左右に振り分け、メニューを上下中央揃えにするので、次のようにCSSを設定します。
header {
justify-content: space-between; /* 左右均等分布 */
}
ul {
align-items: center; /* 上下中央揃え */
}
ボックスを複数行に並べる
つづいて、3カラムのカード部分のレイアウトです。HTMLコードを抜粋したものが下記です。main
タグの中にdiv
タグが8個あります。
<main>
<div class="animal">
<h1>うさぎ</h1>
<img src="images/animal1.jpg" alt="">
<p>全身が柔らかい体毛で覆われている小型獣である。最大種はヤブノウサギで体長 50–76 cm。</p>
</div>
<div class="animal">
<h1>キツネ</h1>
<img src="images/animal2.jpg" alt="">
<p>食性は肉食に近い雑食性。鳥、ウサギ、齧歯類などの小動物や昆虫を食べる。</p>
</div>
(中略)
</main>
div
要素のボックス要素を親要素の1/3
の幅にし、横ならびにしたいので次のようにスタイルを設定するとよさそうです。
main {
display: flex;
}
main div.animal {
width: calc(33.3% - 10px);
margin: 5px;
}
ところが、このコードを実行するとボックスは3カラムにならず、一行に並びます。Flexboxの初期設定では、ボックスは親要素の幅にかかわらず一行に並ぶためです。
複数行のレイアウトを行うには、flex-wrap
プロパティにwrap
を設定します。
nowrap
→ ボックスを単一行に配置するwrap
→ ボックスを複数行に配置する
今回の例では次のように指定します。
main {
flex-wrap: wrap;
}
これで3カラムのカードレイアウトが完成しました。
また、嬉しいことに各カードの高さが揃っています。float
を使ったレイアウトでは、高さ揃えは複数のスタイルを指定したり、JavaScriptを使ったりと煩雑でしたが、Flexboxの場合はプロパティ1つで可能(※)です。
※ align-items
プロパティの初期値がstretch
によるものです。複数行レイアウトの場合、align-items:stretch;
が指定されたボックスの高さは、行の高さの最大値まで広がるため、各行毎に高さが揃います。
ここまでのCSSコードとデモは下記です。
Flexboxでのレスポンシブ対応
「Flexboxがfloat
の代わりに使えることがわかったが、float
の場合のようにレスポンシブなレイアウト対応ができるのか?」という声をしばしば耳にします。Flexboxでのレスポンシブなレイアウト例を見てみましょう。
デバイス幅が500px以下のとき、ヘッダー部分を縦並び、カード部分を2カラムする例です。
2カラムのカードレイアウトは、ボックスの幅を変えることで実現します。
@media (max-width: 500px) {
main div.animal {
width: calc(50% - 10px);
margin: 5px;
}
}
問題はヘッダー部分の縦並びです。
ボックスの並び方向を変更する
Flexboxでは、初期設定の場合ボックスは横方向に並びます。並び方向を変更するには、flex-direction
プロパティを用います。flex-direction
により、主軸と交差軸の方向が替わります。
今回は、縦並びを設定するので、column
を指定します。そして、横方向の中央揃えを指定するために、交差軸方向の並び方設定であるalign-items
プロパティにcenter
を指定します。
@media (max-width: 500px) {
header {
flex-direction: column;
align-items: center;
}
}
justify-content
とalign-items
は横方向、縦方向の並びを指定するのではなく、主軸と交差軸の位置によってボックスの並び方が変わること、そして主軸と交差軸の位置はflex-direction
によって変更されうることに注意してください。
ここまでのCSSコードとデモは下記です。
Flexboxでのクロスブラウザ対応
Flexboxは、仕様策定の過程でさまざまな記法が存在しました。たとえば、Android 4.3以下やIE 10にも対応するには、ベンダープレフィックスや異なる値を用いて次のように記述する必要があります。
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
同様に、主軸方向の並び方justify-content
、垂直軸方向の並び方align-items
等についても記法に違いがあります。Flexboxを使うために異なる記法を都度記述するのは手間で、バグを誘発します。この問題は他のCSS 3プロパティを使う場合にも同じです。こういったベンダープレフィックスの有無、記法の差異を吸収する際は、「Autoprefixer」というツールを使うのがお薦めです。
Autoprefixerを使ってクロスブラウザ対応する
Autoprefixerは、CSSコードを解釈し、必要なベンダープレフィックスを自動で設定したり、異なる記法を出力するなどして、指定のブラウザ向けに必要な出力を行うツールです。
具体的にはGulpのようなタスクランナーや、webpackなどのバンドラーと併せて用いるのがよいでしょう。
簡易な手順でAutoprefixerを使う方法
今回は、Autoprefixerのサンプルを用意しました。Flexboxを使う場合だけでなく、CSS Filtersfilter: brightness(1.0)
やuser-select
のベンダープレフィックス対応といった他CSSプロパティの記述差異吸収においても利用可能です。5つのステップで手軽に利用できるので、ぜひご利用ください。
① GitHubよりpackage.jsonとgulpfile.jsをダウンロードし、プロジェクトフォルダー直下に配置します。
② Node.jsが必要なので、インストールしていない場合は公式サイトからインストールしてください。
③ コマンドラインより、下記コマンドを実行します。
npm install
④ 完了したらgulpfile.js
の次の変数に必要な値を記述します。
// 変換したいCSSファイルのパス
const cssFile = "docs/css/style.css";
// 変換後のCSSファイルを保存するパス
const cssDistPath = "docs/css/";
// 変換後のCSSファイルの名前
const cssDistFile = "style_dist.css";
⑤ コマンドラインで下記コマンドを実行します。
npm run gulp
Flexboxのレイアウト部分のCSSコードが次のように出力され、Flexboxのクロスブラウザ対応ができました。
▼ 変換前のコード(抜粋)
hedear {
display: flex;
justify-content: space-between;
}
▼ 変換後のコード(抜粋)
hedear {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
より詳しくGulpやAutoprefixerについて知りたい方は、下記記事を参照ください。
ここまでのCSSコードとデモは下記です。
Flexbox未対応のブラウザ向けの対応方法(IE 9)
Flexboxに対応しているブラウザの対応はできましたが、未対応のブラウザの対応はどうすればよいのでしょうか? Flexboxは、執筆時点(2016年8月現在)ではほぼすべてのモダンブラウザで対応しています(「Can I use」より)。しかし、IE 9のようなFlexboxに未対応のブラウザへの対応を余儀なくされるケースもあるでしょう。このような場合にはポリフィルを用います。
ポリフィル「flexibility.js」でIE 9でもFlexboxレイアウト
ポリフィルとは、最新のブラウザの機能を古いブラウザでも利用可能にする技術です。Flexboxのポリフィルの1つとして「flexibility.js」があります。Flexboxに対応していないIE 9等のブラウザでもFlexboxが有効になります。
HTMLコードでflexibility.js
を読み込みます。なお、執筆時点(2016年8月現在)の最新版 2.0.1ではIE 9で動作しないバグがあるため、1系を用います。
<script src="https://cdnjs.cloudflare.com/ajax/libs/flexibility/1.0.6/flexibility.js"></script>
CSSコードのdisplay:flex;
を指定している箇所で、-js-display : flex;
を指定します。justify-content
やflex-wrap
のようなプロパティに各々-js-
をつける必要はありません。
header {
-js-display: flex;
display: flex;
}
ul {
-js-display: flex;
display: flex;
}
main {
-js-display: flex;
display: flex;
}
ポリフィルを読み込むことで、IE 9でもFlexboxのレイアウトが適用されます。
完成版のCSSコードとデモは下記です。
Flexboxはボックスレイアウトの新常識
float
に代わるCSS 3のボックスレイアウト手法であるFlexboxは、並び方、折り返し設定、並び方向の設定等、シンプルな記述で豊富なレイアウトが可能です。Autoprefixerやポリフィルと連携することで、多くのブラウザに対応できます。この機会にFlexboxによるボックスレイアウトを始めましょう。
また、CSSレイアウトのための新手法にCSS Grid Layoytというものがあります。気になる方は記事「CSS Grid Layout入門。対応ブラウザが出揃った新しいレイアウト仕様」もあわせてご覧ください。