Flexboxを使いこなして柔軟過ぎるCSSレイアウトを実現しよう。

Web/12 Aug 2015

毎朝アクセス解析を見ていると、IE8 以前のバージョンからの流入が激減しており、喜びを隠せない日々を過ごしています。 実際、クライアント先の学習塾の 4 月から 7 月の IE だけの平均を見ると、IE9 が 10%、IE11 が 75%、残りが IE7、8、10 という割合です。そして、IE での流入数が減った分、モバイルからの流入が増え続けており、モバイル率が 7 割近くまで上がりました。

古いブラウザの割合が減ることは、Web 制作者にとっては嬉しいことで、対応する時間が大幅に減ります。そして、対応ブラウザのバージョンが上がると、Flexboxだって使えるようになります。(← 前置き長い)

Flexbox が CSS レイアウトを楽にする

このサイトは、IE9 以下からの流入が 3% 未満なので、完全に無視して CSS レイアウトは Flexbox を使っています。Flexbox は CSS3 で定義された、柔軟性のあるレイアウトを行うための規格で、floatclearfix、擬似要素を使わないコードで実装できるのが特徴です。

Flexbox には、左右のコンテンツの高さを合わせたり、並び順の方向や向き、等間隔での配置など豊富なプロパティがあり、使いこなせるようになれば楽になること間違いなし。で、これは見た方が早いので、下記に簡単なコードを書きました。

See the Pen jPRENG by mdesign (@mdesign-works) on CodePen.

ヘッダーとフッター、左右のコンテンツと色分けしています。左カラムと右カラムは内包する p 要素の数が異なるため、本来高さが合いません。また、左右配置についても、今までのように float を使っていません。それでもレイアウトを組めるのが Flexbox の特徴です。

.flex-container {
  display: -webkit-flex;
  display: flex;
}

※ プリフィックスについては、次項のブラウザ対応を見てください。

CSS をみると親要素の flex-container クラスに display: flex; が記述されています。これにより、子要素の div.flex-leftdiv.flex-right が flex アイテムとなり、柔軟なレイアウトに対応できるようになります。Flexbox 関連の設定は親要素に記述することが使い始めの重要なポイントです。

まずは対応ブラウザから

興味が湧き始めたところで、現在の対応状況を。

flexの使用状況 ※ ↑ 2015/08/12 時点の対応状況ですが、2015/10 になった今もそこまで変わっていません。

Can I Useで Flexbox のブラウザ対応状況を見ると、IE8 と IE9 は未対応、IE10 はプレフィックス(接頭辞)に -ms- つければ、部分的に使えますが、実質は IE11 以上ですね。

IE10 以下が対応必須な方は実務では使えないかもしれませんが、知識としては重要です。たぶんこれからのスタンダードになると思います。

ブラウザのサポート状況

対応している主要なブラウザバージョンは以下の通りです。(プレフィックス有りで対応化を含む。)

PC ブラウザ

  • IE 11+(最新ブラウザの Edge を対応しています)
  • Firefox 28+
  • Chrome 29+
  • Safari 6.1+( Safari8 未満は -webkit- が必要)
  • Opera 17+

モバイルブラウザ

  • iOS Safari 7.1+( iOS9 未満は -webkit- 必要)
  • Android Browser 4.4+( 4.3 未満は -webkit- 必要)
  • Chrome for Android 42+
  • Firefox for Android 39+

モバイルと PC ともに最新の Safari はベンダープリフィックスなしでも対応したので、 -webkit- は Safari の旧バージョン向けの対策ですね。iPhone 普及率が高い日本では OS を上げずに使っている人も多いので、しばらくは指定することをお忘れなく。

Flexbox を使ってレイアウトしてみる

すべてのプロパティをつらつら書かず、例としてヘッダーを組んで、その中で使いそうなものをピックアップします。自分は実用的な部分がないと頭に入らないタイプなので…。

ヘッダーを組んでみよう

ヘッダーを構成する際、左にロゴ、右にメニューとしているサイトが多くあります。このサイトもデスクトップ表示はそうです。その場合、以下のように floatclearfix を用いて左右配置の CSS レイアウトを実現しているかと思います。Bootstrap の navbar クラスもこんな構成の CSS でしたね。

/*-- clearfix --*/
header:before,
header:after {
  content: '';
  display: table;
}

header:after {
  clear: both;
}

/*-- ロゴ --*/
h1 {
  float: left;
}

/*-- ナビゲーション --*/
nav {
  float: right;
}

上記のようにしても良いのですが、flexbox を使うと下のサンプルのように記述できます。

See the Pen GJLgxW by mdesign (@mdesign-works) on CodePen.

flexbox を使うための flex プロパティ

上記サンプルの header 要素に指定した CSS から見ていきます。

header {
  display: -webkit-flex;
  display: flex;
}

親要素に display: flex; を設定すると、子要素が flex アイテムとして認識されます。つまり、この設定を記述していなければ flexbox は使えません。

flex-direction で要素を並べる方向を指定する

次に ul 要素の CSS を見ると、flex-direction: row-reverse; という記述があります。 flex-direction は子要素の flex アイテムが並ぶ方向を指定するもので、そのプロパティは以下のようになります。

  • flex-direction: row;

    子要素を水平方向に左から右へ並べる(初期値)

  • flex-direction: row-reverse;

    子要素を水平方向に右から左へ並べる

  • flex-direction: column;

    子要素を垂直方向に上から下へ並べる

  • flex-direction: column-reverse;

    子要素を垂直方向に下から上へ並べる

今回は row-reverse を設定し、ナビゲーションのメニューアイテムを右から左に並べています。なので、Codepen の「Result」タブを見ると、「Contact」が左に表示されていますね。

メディアクエリを使ってレスポンシブを実装している場合は、モバイル時のメニュー配置は flex-direction: column; で縦配置とし、デスクトップサイズでは flex-direction: row; で横配置にするといった際に使えそうです。

実際にこのサイトでは、トップページの記事配置に flex-direction を上記の方法で設定しています。

flexを使って記事の並び

試していないですが、並ぶ方向を CSS クラス化し、js でクラスのオンオフ制御すれば静的サイトでも降順昇順の並び替えができそうな気がします。

justify-content で左右中央を自在に操る

Flexibleboxの概念

↑ MDN のCSS flexible box の利用からお借りしましたもので、Flexbox を図解にしたものです。

flex の親要素を flex コンテナ(flex-container)と言い、flex コンテナには始点の main-start と終点の main-end があります。この 2 点を結んだものが main-axis (主軸)です。 justify-content では、この主軸上の配置を制御していきます。

先にこのプロパティで指定できる値を見ると、

  • justify-content: flex-start

    main-start を起点に詰めて配置

  • justify-content: flex-end

    main-end を起点に詰めて配置

  • justify-content: center

    主軸の中央に寄せて配置

  • justify-content: space-between

    最初のアイテムを main-start に、最後のアイテムを main-end に詰めた状態で等間隔に配置する

  • justify-content: space-around

    主軸上に等間隔に配置

今回は、justify-content を説明するために header 要素にあえて使いました。 値に flex-end を設定したことで、起点は main-end となっています。なので、flex コンテナの子要素である、h1nav は右に詰めた状態で配置されることになります。

詰めて配置 justify-content

でも、ロゴが左に寄っているのはなぜ?

と思われたのではないでしょうか。右詰めであれば「LOGO」の h1 は「Contact」と隣接しているはずです。

これは、h1margin-right: auto; を設定したからで、これにより、右に寄ったアイテムと反対の端に配置することができます。 下画像を見ると、マージンが取れていることが確認できますね。

margin-right: auto

align-items 上下位置を操る

justify-content の垂直版です。なので、同様のプロパティ値があります。始点は cross-start、終点は cross-end となり、これらでクロス軸を形成します。

  • align-items: flex-start

    cross-start を起点に詰めて配置

  • align-items: flex-end

    cross-end を起点に詰めて配置

  • align-items: center

    クロス軸の中央に寄せて配置

  • align-items: streth

    クロス軸の大きさに合わせて幅や高さを調整して配置される。(コンテナいっぱいに拡張して表示)

  • justify-content: baseine

    アイテムのベースラインが揃うように配置

今回は、flex コンテナの header 要素の高さをあらかじめ決めており、それに対して align-items: center としたことで、 header クロス軸の中央に各アイテムが揃って表示されているはずです。子要素に heightline-height を設定しなくても良いので、コード量も少なくすみます。

align-items

積極的に取り入れてみては?

基本的な Flexbox のプロパティを中心に紹介しましたがいかがでしょうか。 個人的な見解を言うと、「スマホファーストのサイト制作では積極的に Flexbox を使っても問題ない」と思っています。

というのも、スマホファーストのサイト制作で、PC 表示はおまけ程度という依頼案件が増えているからです。これは私に限った話ではなく、クライアントを見てもモバイルアクセスが 7 割超えているところが複数あります。ターゲット層にもよりますが、特に BtoC だとスマホ率がかなり伸びているのではないでしょうか。逆に IE の下位バージョンはかなり少なくなって、無視できるレベルのところが多いかもしれません。

実際、モバイルからのアクセスが増えると 1 人当たりの PV が減ります。もし、スマホからの閲覧を考慮していないと、より細部まで読まれなくなります。

このような事情を考慮すると、スマホ UI の重要度はかなり高い。Flexbox を使えば UI が良くなるのではなく、「Flexbox を使うことで実現できる表現の幅が広がる」可能性を秘めているということです。そして、従来の冗長な CSS レイアウトと比べて、わずかでも無駄記述やコード量が減り、軽量化となるのであれば使わない理由はありません。

今回改めて Flexbox を調べたことで、このサイトにも取り入れました。グリッドや Clearfix などで構成していたレイアウトを Flexbox に置き換えたことで、コード量がちょっと減りましたよ。それに合わせて、レイアウトのためだけの HTML 要素も合わせて削れたのが良かった。

参考サイト

今回いろいろ調べるにあたり、多くの良記事を発見しましたが、ちゃんと使うのならリファレンス的なものは目を通すべき。個人的には、CSS flexible box の利用という MDN の解説は理解に役立ちましたのでオススメです。