Flexboxで要素を横並びにして要素の数でのレイアウト調整や中央寄せにする



CSS3から追加されたFlexboxは、PCからタブレット端末、スマートフォン端末に対応したレスポンシブWebデザインのレイアウト構築に優れています。要素の横並びから要素の高さを揃えたり、また上下左右中央寄せなども手軽に実装することができます。

要素をグリッド(格子)のように並べるグリッドレイアウトを採用したデザインでは、均等に横並びにして配置を整えていくので、可変幅にもうまく対応していく必要があります。

今までも横並びのレイアウトに対応する方法として「display: inline;」や「display: table;」「display: table-cell;」、ほかclearfixといったテクニックを利用していくことで実装できました。それぞれに癖があることもあり使い方は様々でした。

CSS3から追加されたFlexboxを利用することで手軽に横並びにでき、またデバイス幅や可変にしっかりと対応することができます。

Flexboxでは可変に対応した便利なプロパティがいくつかありますが、ここでは横並びのレイアウト調整や中央寄せに対応するプロパティをご紹介します。

サンプルとして、
メディアクエリを利用してPCやタブレット端末では3つの横並びに。余りは中央寄せのレイアウトにしてみます。

横並び(子要素の数で調整)


Flexboxを利用して、要素の数によって横並びにしてバランス良く配置していきます。

まずはHTMLから。

HTML

<article>
  <section class="flex">
    <div class="flex-item">
      <img src="images/img-sample.jpg" alt="Flexbox Sample Image">
      <p>Example text... Example text... Example text... Example text... </p>
    </div>
    <div class="flex-item">
      <img src="images/img-sample.jpg" alt="Flexbox Sample Image">
      <p>Example text... Example text... Example text... Example text... </p>
    </div>
    <div class="flex-item">
      <img src="images/img-sample.jpg" alt="Flexbox Sample Image">
      <p>Example text... Example text... Example text... Example text... </p>
    </div>
    <div class="flex-item">
      <img src="images/img-sample.jpg" alt="Flexbox Sample Image">
      <p>Example text... Example text... Example text... Example text... </p>
    </div>
    <div class="flex-item">
      <img src="images/img-sample.jpg" alt="Flexbox Sample Image">
      <p>Example text... Example text... Example text... Example text... </p>
    </div>
  </section>
</article>



横並びにする要素の親要素であるsectionに「grid」というクラスを付けて、CSSにてFlexboxのレイアウト技法で子要素の横並びを実装していきます。

CSS

article {
  margin: 4%;
}

.flex {
  padding: 1%;
  background: #e0e0e0;
}

.flex-item {
  margin: 4%;
  padding: 4%;
  background: #f7f7f7;
}

@media screen and (min-width:768px) {

  article {
    margin: 2%;
  }

  .flex {
    max-width: 1200px;
    margin: auto;
    padding: 1%;

    display:-webkit-box;
    display:-ms-flexbox;
    display:flex;

    -webkit-box-orient:horizontal;
    -webkit-box-direction:normal;
    -ms-flex-flow:row wrap;
    flex-flow:row wrap;

    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
  }

  .flex-item {
    margin: 1%;
    padding: 1%;
    width: calc(100% / 3 - 4%);
  }

}



CSSでは初めに全体の見た目のデザインとして、articleや要素関連にスタイルをしていしています。
メディアクエリでは最小幅が768px、タブレット端末以上のデバイスに対してFlexboxで横並びを実装します。

まず、親要素を「display: flex;」としてFlexコンテナとします。こうすることで子要素であるdivはFlexアイテムとなります。

flex-flowは「flex-flow:row wrap;」として、Flexアイテムの配置方向と折り返しを指定します。行として折り返す指定になります。
こちらはflex-directionの「flex-direction: row;」とflex-wrapの「flex-wrap: wrap;」をショートハンドで書いたものになります。

justify-contentでは、子要素のFlexコンテナをインライン軸に沿った配置をしていきます。
行の横並びの要素の数が足りなくても、中央に寄せてバランスをとるように「justify-content: center;」を指定します。

以下、実際の表示になります。

Flexboxを利用したFlexアイテムの横並び



Flexboxはメディアクエリでタブレット端末以上にしか指定していないので、スマートフォンサイズでは縦並びとなります。

スマートフォン端末のレイアウト



justify-contentプロパティでは他にも、両端に余白を入れて均等間隔に配置する「space-around」などの指定もあります。

CSS

.flex {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-pack: distribute;
  justify-content: space-around;
}



これらのFlexboxプロパティは、古いWebブラウザにも対応するために、ベンダープレフィックスも記述しています。

Flexbox(Flexible Box Layout Module)の対応状況
https://caniuse.com/#search=CSS%20Flexible%20Box%20Layout


ベンダープレフィックスとは、ベンダーがCSS3の拡張機能を実装するのに使用する識別子になります。
古いブラウザにも対応させるときに指定します。

IE6 ~ 9 : 非対応
IE 10,11 : -ms-
Chrome、Safari、iOS Safari、Android : -webkit-



Firefoxはベンダープレフィックスで「-moz-」をよく見かけますが、Flexboxについては特に関係ありません。
古いブラウザは動かないですし、Firefox 20以降は動きます。

どのWebブラウザも最新バージョンを利用していれば問題ないです。
Windows 10からデフォルトで搭載されているMicrosoft製のEdgeは対応しています。
気になるのはIEくらいです。

ベンダープレフィックスはFlexプロパティごとで記述が変わってきます。

Flexアイテムを3つ並びにするため、子要素のdivにはcalc関数を使って各コンテンツ幅を余白分も含め、「width: calc(100% / 3 – 4%);」として均等に3つに分けて計算しています。

calc関数の利用もブラウザによっては注意が必要です。

calc関数ブラウザ対応状況
https://caniuse.com/#search=calc

Google ChromeやFirefox、Safari、Edgeといった主要ブラウザは対応していますが、IEは正しく機能しません。
例えば、3つ横並びにするときに各要素の幅を「100% / 3」と計算しますが、結果が「33.33333…」と割り切れません。これをChromeやFirefoxなどのWebブラウザはうまく対応してくれますが、IEでは割り切れないと1つ繰り上げる処理をするので、各要素の合計幅が100%を超えて表示が崩れます。

IEもしっかり対応する場合には、以下の2つの記述のどちらかを指定すると良いでしょう。

/* IE対応 */
width: calc(99% / 3 – 4%);
width: 33%;



また、CSSハックでIEだけ対応するCSSを指定してもいいですね。
CSSハックについてはこちらでご紹介しています。



ちなみに、Flexboxでは横並びのFlexアイテムの高さは、コンテンツの量が違っても高さが揃います。
これはデフォルトで「align-items: stretch;」が有効であるためです。

上下左右中央寄せ


続いて、要素を上下左右の中央に配置する方法です。

今まではpositionプロパティを利用したり、インライン要素にしていろいろ試行錯誤していくことが多かったですが、Flexboxではとてもシンプルに実装することができます。

まずはHTMLです。

HTML

<section class="layout-center">
  <div></div>
</section>



親要素のsectionの中に、子要素としてコンテンツを入れるためのdivを用意してみました。

続いてCSSです。
親要素をブラウザの画面全体を要素範囲として、背景に画像を入れてみました。

CSS

.layout-center {
  width: 100%;
  height: 100vh;
  background-image: url("../images/img-sample-alpha.jpg");
  background-size: cover;

  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;

  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;

  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}

.layout-center div {
  width: 80%;
  max-width: 600px;
  height: 315px;
  background: rgba(255,255,255,.7);
}



はじめに「display:flex;」を指定して親要素をFlexコンテナ、子要素をFlexアイテムとします。
ここから「align-items」や「justify-content」のプロパティを使って、子要素の上下左右中央寄せにします。

どちらのプロパティもcenterを指定することで中央に配置されます。

「align-items: center;」 : 上下中央寄せ
「justify-content: center;」 : 左右中央寄せ



それぞれで見ていくと以下のようになります。

FlexboxでのFlexアイテムの中央寄せ



ですので、2つのプロパティを利用することで上下左右中央寄せとなります。

FlexboxでのFlexアイテムの上下左右中央寄せ



Flexboxの2つのプロパティだけで実装できるのはとても楽ですね。

まとめ


今までは意外と手間が掛かっていた要素の横並びや中央寄せも、Flexboxというレイアウト技法を使うことでシンプルで簡単に実装できます。
意外と手こずる横並びの要素の高さを揃えることも、Flexboxのプロパティで解決するのでとても便利です。

Flexboxは昔からある技法ではないので、ベンダープレフィックスを指定しながら古いブラウザにも対応していくと良いでしょう。

IE9以前のブラウザに対応するのであれば、手間はかかりますが万能なClearfixを利用する方法がいいです。IE9以降や各Webブラウザの最新バージョンであればFlexboxは問題なく使って大丈夫です。