CSSレイアウトにfloatは古い!
初心者でも始められるFlexbox入門

615
700
976

ボックス要素の横並びを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つの過程が必要です。

  1. ボックスをFlexboxレイアウトとして指定する
  2. ロゴとメニューを左右に振り分ける
  3. ヘッダー内を縦方向中央揃えにする

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-contentalign-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.jsongulpfile.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-contentflex-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入門。対応ブラウザが出揃った新しいレイアウト仕様」もあわせてご覧ください。

オンライン動画で、もっと丁寧に解説してます

筆者はビデオトレーニングサイトLynda.comで「Flexbox入門」の講師をしています。今回紹介した内容に加え、実践的なレイアウト方法までを詳しく動画で解説しているので、Flexboxの知識を体系的に学習できます。もし、この記事でわからなかったことや、現場での使い方を知りたい方はご覧くださいませ。

※この記事が公開されたのは3年1ヶ月前ですが、 平成30年3月9日に内容をメンテナンスしています。