フレックスボックスの典型的な用途

このガイドでは、フレックスボックスの一般的な使用例を紹介します。 — 他のレイアウト方法よりも適した使い方です。

なぜフレックスボックスを選ぶのか?

ブラウザーが完全対応しているならば、アイテムの集まりをある方向へ並べる用途にはフレックスボックスが適しています。アイテムを並べる際には、コンテナーの内部でのアイテムの寸法や、アイテム同士の余白を調節したくなると思います。フレックスボックスはそのような用途のために設計されています。フレックスボックスと CSS グリッドレイアウトとの違いについては フレックスボックスと他のレイアウト方法の関係 をご覧ください。そこでは、フレックスボックスが CSS レイアウトの全体像にどのように適合しているのかを説明しています。

現状では、グリッドレイアウトのほうが適しているけれどもそれを使えない、という場面でもフレックスボックスはよく使われます。また、アイテムを整列する手段としても使われます。これは、Box Alignment がブロック要素のレイアウト方法として実装されれば解決するでしょう。このガイドでは、現状での典型的なフレックスボックスの使用例を紹介します。

ナビゲーション

ナビゲーションのよくあるパターンとして、水平な棒状にリストを表示するというものがあります。このパターンは見た目とは裏腹に、フレックスボックスの登場以前は実現が難しいものでした。フレックスボックスならばとても簡単であり、うってつけの出番だと言えます。

水平方向に表示したいアイテム群がある場合、空間が残ることがあります。この空間をどうするかを決めなければなりませんが、いくつかの選択肢があります。アイテムの外側に空間を表示して、アイテムの間や周囲に余白を設けるか、アイテムの内側に空間を吸収して、アイテムを伸長してこの空間を占めるようにするか、どちらかにする必要があります。

アイテムの外側に空間を分配

アイテムの間または周囲に空間を分配するには、フレックスボックスの配置プロパティと justify-content プロパティを使います。このプロパティの詳細については、フレックスコンテナーにおけるアイテム配置をご覧ください。そこでは、主軸 (横軸) におけるアイテムの配置について説明しています。

下記のライブ例では、アイテムをそれぞれ本来の大きさで表示しています。また、justify-content: space-between によって、アイテム同士の間に同じ幅の余白を配置しています。値に space-around や、ブラウザーが対応している場合は space-evenly を指定することで、余白の配置方法を変えることができます。flex-start で余白をアイテム群の後ろに配置したり、flex-end で余白をアイテム群の前に配置したり、center でアイテム群をナビゲーションの中央に配置したりすることもできます。

アイテムの内側に空間を分配

ナビゲーションでのもう一つのパターンは、空間をアイテムの間ではなく、アイテム自身の内部に配置することです。この場合は、flex プロパティを使うことで、アイテムを互いの比率を保ったまま伸縮することができます。主軸に沿ったフレックスアイテムの比率の制御に書かれている通りです。

ナビゲーションのアイテムの幅を同じにしたいなら、flex: auto を指定します。これは flex: 1 1 auto の一括指定です。すべてのアイテムは自動の flex-basis をもとに伸縮します。つまり、他よりも中身が多いアイテムは、占める空間も他より多くなります。

下記のライブサンプルの flex: autoflex: 1 に変えてみてください。これは flex: 1 1 0 の短縮版で、すべてのアイテムの幅が同じになります。なぜなら、flex-basis が 0 となって空間が均等に分配されるからです。

ナビゲーションの分割

主軸 (横軸) でアイテムを整列するもうひとつの方法は、auto マージンを使うことです。これにより、一方のアイテム群を左揃えにして別のアイテム群を右揃えにする、というナビゲーションバーのデザインパターンが可能になります。

下記の例では、主軸上での位置合わせのための_auto_マージンの使用に書かれている auto マージンの技法を使っています。アイテムは flex-start によって主軸上に配置されます。これはフレックスボックスの既定の挙動です。そして、左マージンに auto を指定することで、そのアイテムだけは右に配置されます。分割される位置を変更するには、CSS の "push-right" クラスを別のアイテムに移してください。

下記の例では、フレックスアイテムにマージンを指定して、アイテム間の空間を作っています。また、フレックスコンテナーに負のマージンを指定して、コンテナーの幅いっぱいにアイテムを表示するようにしています。Box Alignment の仕様にある gap プロパティがフレックスボックスに実装されるまでは、このようにマージンを使う必要があります。

アイテムの中央揃え

フレックスボックスの登場以前、開発者たちは「ウェブデザインで最も難しいのは垂直方向の中央揃えだ」と冗談を言っていました。下記のライブサンプルのとおり、フレックスボックスの配置プロパティを使用することで、簡単に解決できるようになりました。

配置では、flex-start でアイテムを先頭に、flex-end で末尾に配置することができます。

将来、Box Alignment の各プロパティがブロック要素のレイアウト方法として完全に実装されれば、単一のアイテムの中央揃えのためにフレックスコンテナーを作る必要はなくなります。しかし現状では、1 つのものを別のものの中で正確に中央に配置したければ、フレックスボックスを使うことになります。上記の例のように、コンテナーをフレックスコンテナーとして扱ってフレックスコンテナーに align-items を指定するか、フレックスアイテム自身に align-self を指定してください。

フッターが下端に張り付くカード

フレックスボックスや CSS グリッドを使ってコンテナー内のカード状の部品を並べて配置する場合、それらの制御はコンテナーの直下の要素であるカード自身にしか及びません。どういうことかと言うと、各カードの中身の量が異なる場合、カードはグリッド領域やフレックスコンテナーの高さに引き伸ばされます。そして、カードの内部では通常のブロックレイアウトが用いられます。つまり、中身の量が少ないカードでは、カードのフッターはカードの下端に張り付くのではなく、フッターが下端から浮き上がってしまいます。

2 枚のカード部品は、部品の内部がラッパーと一緒に伸びることはない。

フレックスボックスはこれを解決できます。カード自身もフレックスコンテナーにして、flex-direction: column を指定します。そしてカードの本文領域に flex: 1 を指定します。これは flex: 1 1 0 の一括指定です。アイテムは 0 の flex-basis をもとに伸縮します。引き伸ばせるフレックスアイテムが本文領域だけの場合、本文領域はフレックスコンテナー内の空間をすべて取り込み、フッターを下端に張り付かせます。ライブサンプルから flex プロパティを削除すると、フッターが本文の真下に移動するのを確認できます。

メディアオブジェクト

メディアオブジェクトは、ウェブデザインでよく見られるパターンです。このパターンでは、画像やその他の要素が片側に、テキストが右側に配置されています。メディアオブジェクトは、反転させることができるのが理想です。すなわち、画像を左から右に移動することです。

このパターンは、コメント欄をはじめ、画像や説明を表示する必要がある場所でよく見られます。フレックスボックスを使用すると、画像を含むメディアオブジェクトの部分が画像から大きさを取得し、メディアオブジェクトの本文が残りの空間を確保するように拡大縮小します。

下のライブ例では、メディアオブジェクトが表示されています。配置プロパティを使用して、横軸のアイテムを flex-start に揃え、.content のフレックスアイテムを flex: 1 に設定しています。前述のカラムレイアウトカードのパターンと同様に、flex: 1 を使用することで、カードのこの部分を伸長させることができます。

このライブ例では、デザインの中でメディアオブジェクトを制約するさまざまな方法を試してみることができます。

画像が大きくなりすぎるのを防ぐには、max-width を画像に指定します。画像領域のフレックスボックスの指定は初期値のままなので、縮むことはできますが伸びることはできません。また、初期値では flex-basis は auto なので、画像の width や max-width が flex-basis となります。

.image img {
  max-width: 100px;
}

両方の領域の比率を維持したまま伸縮させることもできます。両者に flex: 1 を指定すると、0 の flex-basis をもとに伸縮することになります。つまり両者の幅は同じになります。内容物を元に、両方とも flex: auto に設定すると、内容物の寸法や、画像の幅などフレックスアイテムに直接適用される大きさに合わせて拡大縮小することができます。

.media .content {
  flex: 1;
  padding: 10px;
}

.image {
  flex: 1;
}

両者に別々の flex-grow の比率を指定することもできます。例えば画像領域には flex: 1、文章領域には flex: 3 というように。これは、両者に 0flex-basis が適用されますが、指定された flex-grow に従って別々の比率で領域が確保されることを意味します。このように使用される flex プロパティについては、主軸に沿ったフレックスアイテムの比率の制御で詳しく説明されています。

.media .content {
  flex: 3;
  padding: 10px;
}

.image {
  flex: 1;
}

メディアオブジェクトを反転させる

画像が右で文章が左になるようにメディアオブジェクトの表示を切り替えるには、flex-direction プロパティに row-reverse を指定します。下記のライブサンプルでは、flipped のクラスを .media の隣に追加することで実現しています。HTML からそのクラスを削除すれば、どのように表示が変わるのかが分かるでしょう。

フォームコントロール

フレックスボックスはフォームコントロールのスタイル指定に関しては特に便利です。フォームにはたくさんのマークアップや小さな要素があり、それらを配置したいと考えるはずです。よくあるパターンは <input> 要素と <button> の組み合わせでしょう。検索フォームや、単に訪問者にメールアドレスを入力してもらう用途などで使われます。

フレックスボックスならばこのようなレイアウトを簡単に実現できます。下記の例では、<button><input> フィールドを枠線と display: flex を指定したラッパーの中に入れています。<input> フィールドを引き伸ばすために flex プロパティを使っています。ただし、ボタンは引き伸ばされません。つまり、確保できる領域の変化に応じて伸縮する入力欄を備えたフォーム部品を実現できます。

ボタンを右側に置いたのと同じように、ラベルやアイコンを左側に置くことも簡単にできます。今回はラベルを置きました。背景色以外は、何もレイアウトを変更していません。伸縮する入力欄は少し狭くなるものの、2 つのアイテムが取った残りの領域をすべて使うことになります。

このようなパターンのおかげで、デザインに合わせたフォーム要素のライブラリーを簡単に作れます。要素の追加にも簡単に対応できます。伸縮するアイテムとしないアイテムを組み合わせる用途では、フレックスボックスの柔軟性の恩恵を存分に受けることができるのです。

終わりに

上に挙げたパターンを見て回るうちに、フレックスボックスの最適な利用場面を考え始めたことと思います。いろいろな選択肢があることでしょう。伸縮するアイテムとしないアイテムを組み合わせたり、フレックスアイテムの中身のサイズをフレックスアイテム自身に反映させたり、比率に沿ってフレックスボックスの領域を分け合ったり。すべてはあなた次第です。

コンテンツの最適な表現方法を思い描いてみてください。そしてその実現にあたって、フレックスボックスや他のレイアウト方法をどのように利用できるのかを調べてみてください。