テーブルタグが唯一のWebページをレイアウトする手法だった頃を覚えていますか? 表形式のデータを表示するための機能をレイアウトに無理やり使っていたので、タグ名の意味と用途が異なるひどい状態でした。新しい「道具」が必要になり、「正しい」レイアウト方法としてfloatと絶対位置指定による手法が登場しました。
しかしテーブルタグ同様、floatと絶対位置指定の目的はWebサイトを整形することではありません。
主要ブラウザーがCSSで機能する頼れるレイアウトエンジン、CSSグリッドレイアウトをサポートしました。非対応のブラウザーに対する互換措置をすれば十分使えます。
互換性確保の方法は、Flexboxベースのレイアウト(W3Cが好む言い方だとFlexible Boxレイアウトモジュール)を、すべてのCSSグリッド非対応ブラウザーに提供します。Flexboxのブラウザーサポートは充実しているので、ほとんどの場合に有効です。
Flexboxの利点
Flexboxの強みをまとめました。
- ページにコンテンツを上下左右どの方向にでも揃えて配置できる
- ページ内要素の並び順を変更できる
- 使える領域の広さに合わせて各部品を(Flexboxの名の通り)伸縮して、コンテナ要素や要素同士の位置関係を基準にして整列できる
- 複数カラム(列)の高さを、コンテンツの差に関わらず合わせるレイアウト(equal-height)が簡単にできる
以下のレイアウトでFlexboxのプロパティと可能性を解説します。
<div class="example">
<header>
header content here
</header>
<main class="main">
<nav>
nav content here
</nav>
<div class="content">
main content here
</div>
<aside>
aside content here
</aside>
</main>
<footer>
footer content here
</footer>
</div>
最初に、.mainクラスの中の要素、<nav>、<aside>、および<dev>を、横一列で配置します。Flexboxを使わない場合、3つの要素をfloatにしても、思った通りのレイアウトできないこともあります。カラムの高さがコンテンツに応じて変わるので、すべてのカラムに同じ高さを設定するか、技を駆使してそろえる必要があるのです。
Flex要素にしてみよう
Flexboxの核は、コンテナ要素に対してdisplayプロパティ値をflexに指定して、コンテナの子要素がすべて「flex要素」にすることです。flex要素にはいくつかの便利なプロパティが備わっています。たとえば、要素の幅は未指定でも自動でスペースを埋めて、横一列に並びます。
コンテナクラス.mainにdisplay: flexを設定すると、子要素.contentは自動で<nav>と<aside>の間に収まるように収縮します。計算が不要で便利です。おまけに3つの要素は魔法のように揃って同じ高さになるのです。
.main {
display: flex;
}
詳細は以下のデモを見てください。
並び順の変更:Flexboxのorderプロパティ
Flexboxが持つもう一つのプロパティは、要素の並び順を簡単に操作する機能です。たとえば上記レイアウトを製作したところ、クライアントから「.contentは<nav>の前に配置してほしい」と言われたとします。
通常ならHTMLを開いて要素の並びを変更しますが、flexboxならCSSだけで達成できます。.contentのorderプロパティを-1に設定したカラムが1番目になります。
.main {
display: flex;
}
.content {
order: -1;
}
ほかのカラムの順番に指定を加える必要はありません。
あえて明示的にorderプロパティで各カラムの順番を明記したいなら、.contentのorderを1にして、<nav>を2に、<aside>を3に設定します。
HTMLから独立したCSSによるレイアウト指定
まだクライアントは満足しません。今度はページの最初に<footer>が来て、<header>よりも前に置いてほしいとの要望がありました。Flexboxの出番です。今度はmainクラス中の要素でなく外側の要素も並び替えるため、display: flexを、外側(対象の要素をすべて包んでいる)<div class="example">に設定します。Flex要素のコンテナを入れ子にできるのです。
<header>、<main.main>、<footer>は上下に積み重なっているので、まず垂直方向を設定します。flex-direction: columnと指定するだけです。加えて<footer>にはorderの値に-1を設定すると、ページ上で先頭に表示されます。とても簡単です。
.example {
display: flex;
flex-direction: column;
}
footer {
order: -1;
}
横方向に並んだ要素を縦方向に並べ直したり、あるいはその逆にしたい場合は、flex-directionプロパティを使い、columnかrowに設定します(初期値はrow)。
キーボード操作(Tabキーなど)でWebサイトを閲覧するユーザーもいます。HTML内に書かれた要素の並び順と実際の画面表示の並び順が食い違うと、サイトの使い勝手が格段に悪化します。詳しは、アクセシビリティとユーザビリティの専門家Adrian Roselliによる洞察HTML Source Order vs CSS Display Orderを参照してください。
Flexboxで要素の位置を揃える方法
Flexboxは、子要素を簡単に水平や垂直方向に揃えられます。
Flexコンテナ内の要素に、align-itemsを指定すると、同じ位置に一律で揃えられます。別々に位置を揃えたいときはalign-selfを使います。要素の位置揃えの方向はflex-directionプロパティの値により異なります。row(要素が水平方向に並ぶ)なら、位置揃えは縦方向に調節でき、column(要素が垂直方向に並ぶ)なら、位置揃えは水平方向に調節できます。
コンテナ要素に、別々の基準で位置揃えしたい図形が複数あるときは、
- 各図形のalign-selfプロパティに適切な値を入れる。使える値:center、stretch(コンテナ要素に合わせた大きさ)、flex-start、flex-end、baseline(コンテナ要素のベースラインに合わせる)
- 親のコンテナ要素にdisplay:flexを設定
- 親コンテナ要素のflex-directionプロパティによって子要素の位置揃え方向が変わる
.example {
display: flex;
flex-direction: column;
}
.red {
align-self: center;
}
.blue {
align-self: flex-start;
}
.pink {
align-self: flex-end;
}
試しに下記デモで親コンテナ要素のflex-directionプロパティをrowからcolumn、あるいはその逆に切り替えると、前述の位置揃え方向が変わることが分かります。
親コンテナ要素内のすべての要素を同じ基準で位置揃えするなら、親コンテナ要素に対してalign-itemsプロパティを使います。使える値は、center、flex-start、flex-end、stretch(初期値。複数要素の大きさがコンテナ要素に合わせて調整されて並ぶ)、baseline(コンテナ要素のベースラインに合わせて一直線に並ぶ)です。
.example {
display: flex;
align-items: center;
}
親要素のflex-directionプロパティの値のrowとcolumnを変えて、align-itemsの値による結果の違いを確認してください。
要素の左右寄せや均等割り付け
位置揃えのプロパティはjustify-contentもあります。スペースの中で複数の要素を均等に配置したい場合に便利です。
使える値は、center、flex-start、flex-end、space-between(両端をぴったり合わせて残りを均等割り付け)、space-around(等間隔に配置され、両端にも同じくスペースができる)です。
単純なHTMLテンプレートの<main>要素には、<nav>、.content、<aside>の3要素がありました。これらはページの左側に押し付けられるように位置します。3つの要素の間には少し隙間を空けて、ページの左端と右端は空けない場合は、親コンテナクラス.mainのjustify-contentプロパティにspace-betweenを設定します。
.main {
display: flex;
justify-content: space-between;
}
値をspace-aroundにし、違いを確認してください。
上記デモでは<header>要素内の文字も、justify-contentプロパティ(水平方向にセンタリングするため)とalign-items(垂直方向にセンタリングするため)の値をcenterにして、中央に寄せています。
header {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
Flexboxで要素の大きさの比率を操作する
flexプロパティは、flexコンテナ内のほかの要素を基準に要素の長さを調節できます。
flexプロパティは、下記の各プロパティのショートハンド(略記)にあたります。
- flex-grow:コンテナ内にあるほかのflex要素と比較して、コンテナ要素の大きさが変化した際にその要素が伸長する割合を係数で指定
- flex-shrink:コンテナ内にあるほかのflex要素と比較して、コンテナ要素の大きさが変化した際にその要素が縮小する割合を係数で指定
- flex-basis:要素の長さ。使える値は、auto、inherit、%、px、emなどの単位に続けて数値で指定
たとえば、高さが揃った3本のカラムを作るには、各カラムにflex: 1を設定します。
nav, aside, .content {
flex: 1;
}
コンテンツ領域に<nav>と<aside>の2倍の幅を指定するには、.contentクラスにflex: 2を設定し、残り2つのカラムは1のままにします。
flexプロパティの使い方に、上記flex-grow、flex-shrink、flex-basisを設定することも可能ですが、本記事の範疇を超えるため割愛します。
参考資料
さらにFlexboxを学びたいなら、以下の資料を参考にしてください。
- ECサイトの定番「メガメニュー」をFlexboxでさくっと作る
- 3つのモダンツールに学ぶ、Flexbox Gridsの使い方
- まだfloat使ってるの? フォームのレイアウトはFlexboxで超簡単に実装できる
最後に
Webサイトの要素の位置を操作したいならFlexboxを使えば仕事はずっと楽になります。Flexboxは鉄壁です。これまでの妥協策や、折り畳みコンテナ、そのほか奇妙な方法をすべて過去のものにしてくれます。
本記事は2013年2月4日の記事を更新したものです。
更新内容:flexboxのブラウザー対応状況の変化とCSSグリッドレイアウトの登場に合わせた記事内容の修正、CodePenデモの作成、コードの修正、タイトルの変更、アイキャッチ画像の追加、いくつかの言い回しの変更など
(原文:A Friendly Introduction to Flexbox for Beginners)
[翻訳:西尾 健史/編集:Livit]