CSS「Flexbox」の使い方。グリッドレイアウトを自在に操ろう!

最終更新:2017-09-20 by Joe

CSSのFlexboxプロパティを使ってグリッドレイアウト(格子)を作成します。

Flexboxに関するプロパティは、なんだかたくさんあって、複雑でよくわからない、もう覚えられない!やっぱまだ Float にしておこう・・、の状態が長く続いているので、まとめました。

Flexboxとは?

Flexboxとは、「グリッドレイアウト」と呼ばれる、格子状のレイアウトをより直感的に実現するために導入されました。CSS3で新規追加された比較的新しいプロパティです。

CSSではよくあることですが、ブラウザ(Chrome, Firefox, Microsoft Edge, … )などで、プロパティのサポート状況がまちまちなので、なかなか開発者の間に利用が広まりませんでしたが、近年、ブラウザのバージョンアップが進み、エンドユーザ環境におけるサポート率が高まってきたため、利用しやすくなってきました。特に、問題となりやすいInternet Explorer 10移行でも、ほぼサポートされていますので、9以前を無視すれば、ほぼ利用可能と考えてよいでしょう。

flexboxのサポート状況の確認は「Can I Use」というサイトが便利です。

種々のブラウザでも、最新版ではほぼグリーンとなっています。

Flexboxのサポート

Felxboxのプロパティ

さて、FlexboxのCSSプロパティ、こちらは、1行3列の簡易的なグリッドレイアウトの例です。

HTML

<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

CSS

.container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-around;
  align-items: center;

  height: 200px;
  width: 100%;
  background-color: #eee;
}

.container .item {
  width: 25%;
  margin-bottom: 10px;
  flex: 0 1 auto;

  background-color: #faa;
  height: 90px;
}

実装例です:

See the Pen CSS: Flexbox by Joe (@akajoe) on CodePen.0

.itemで、適当にwidthを調整すれば、3カラム、4カラムと好きに設定できるでしょう。

ベンダープリフィックスについて

上記では省いておりますが、CSSのベンダープリフィックスが必要な人は、適宜付加して下さい。

付加するにはオンラインもあります:

基本的にベンダープリフィックスはあまり人間が手書きでケアしない方がよいとは思います。

Flexboxの要素 (.container) のプロパティ

詳しく見てみます。一つずつみると、そんなに難しくない、ような気もしますね。

flex-direction

横方向か、縦方向に展開するかです。普通グリッドを使うのは横方向なので、ほとんどの場合「row(デフォルト値)」で良いでしょう。columnで縦に並びます。

reverseをつけると逆方向になりますが、これもほとんど使うことがないでしょう。RTL(Right To Left)と呼ばれる、右から左に書く言語(アラビア系言語)で使うかもしれません。

プロパティ意味
row横方向。左から右へ(デフォルト)
row-reverse横方向。左から右へ
column縦方向。上から下へ
column-reverse縦方向。下から上へ

flex-wrap

要素がコンテナ内で折り返し改行するかどうかです。グリッド(格子)レイアウトを作るのであれば、多くの場合折り返すので「wrap」を選択すると思います。

ただい、アイテムの幅x要素の数が、コンテナの横幅を超えないのであれば、折り返すかどうかの問題んいなりませんので、どちらでも構いません。

プロパティ意味
nowrap行端で折り返さない
wrap行端で折り返す
wrap-reverse行端で折り返し、反対向きに進む。

justify-content

「justify」とは、左揃え、中央揃え、などの文字揃えにおいて、「ちょうどよく分配する」という意味を持ちます。個々のアイテムの幅の合計値がコンテナより小さい場合、余白が生まれてしまうのでそれをどう処理するか?ということです。

flex-startを利用すると、floatを使ったグリッドのような使い心地に近いかもしれません。centerはあまり使いませんね。flex-start, space-around, space-between のいずれかを使うと思います。

プロパティ意味
flex-start行(列)の開始側に寄せる(デフォルト)
flex-end行(列)の終了側に寄せる
center行(列)の中央に寄せる
space-between個々の要素に均等にスペースを与える。行(列)の端はスペースなし。
space-around個々の要素に均等にスペースを与える。行(列)の端にもスペースあり。

align-items

アイテムの配置と垂直方向の長さと、コンテナ高さとの余白をどう処理するかを一括で指定します。だいたいflex-start を使うと思います。たまにcenterも使うかもしれません。

プロパティ意味
flex-start行(列)の開始端に寄せる
flex-end行(列)の終了端に寄せる
center中央に整列
baselineテキストのベースラインに沿う
stretch余白を与えないように引き伸ばされる

align-content

アイテムの配置と垂直方向について、余白の扱い方を定義します。Justify-contentと垂直軸の設定、というわけです。プロパティ名が分かりにくい。

プロパティ意味
flex-start列(行)の開始側に寄せる(デフォルト)
flex-end列(行)の終了側に寄せる
center列(行)の中央に寄せる
space-between個々の要素に均等にスペースを与える。列(行)の端はスペースなし。
space-around個々の要素に均等にスペースを与える。列(行)の端にもスペースあり。

子要素 (.item) のプロパティ

order

アイテムの順番です。整数を指定すますが、これを変更することは稀でしょう。

flex-grow: <number>

アイテム横幅の合計値がコンテナ幅より小さかった時、1以上の整数を指定すると、横幅を拡大させる事ができます。アイテムの拡大比率は、この数字同士の「比率」になります。デフォルトは0です。

例えば、1:2:1だと、真ん中が2倍大きくなります。

なんだかコントロールしにくいので、あまり使わないと思います。デフォルトの0でOK。

flex-shrink: <number>

アイテム横幅の合計値がコンテナ幅より大きかった時、自動で、横幅を縮めて、フィットさせます。アイテムの縮小比率は、この数字の比率になります。デフォルトは1です。

あまりこれも変更して使わないと思います。デフォルトの1でOK。

flex-basis

アイテムの横幅をしています。autoであれば、width値を参照しますので、CSSを扱う人にとって、自然な仕様になります。デフォルトでは、autoです。

widthでいつもどおり指定した横幅を採用できるよう「auto」で使うのが無難ではあるように感じます。ですので、これもデフォルトのままにして、頻繁には変更しない使わないと思います。

align-self

もともとコンテナ側のalignに指定していた値を、アイテム個別に上書きします。これを使うことは稀でしょう。

ぜひショートハンドを利用しましょう

ということで、グリッドの子供要素の方のプロパティは、ほとんど使わないですね。覚えなくてよいのでは・・。

flex-grow, flex-shrink, flex-basis3つはショートハンドの利用が推奨されます。個人的には、デフォルトからほとんど変更することがないので、もはや書かなくていい気もします。

.container .item{
  flex: 1 0 auto;
}

Flexboxのグリッドレイアウトのサンプル

3カラムのグリッドレイアウト

冒頭で紹介したものとほぼ同じです。コンテナ横長の30%としているので、3カラムになり、残り10%の余白をアイテムたちがわけあいます。

  • 3カラムのグリッド
  • 横方向に並べて
  • 横端で自動で折り返し
  • 両端のアイテムはコンテナ枠にピッタリくっつく
.container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
}
.container .item{
  flex:0 1 auto; /* Default */
  width:30%;
}

人気がでたら、あとで、もう少し追加します。今日はここまででお願いします。