そこが知りたい、Flexbox 第1回 仕様を知る 1
この記事では、CSS Flexible Box Layout Moduleによるカラムレイアウトの仕様を解説します。フレックスコンテナと、フレックスアイテム、それぞれに設定できるプロパティを紹介します。
基本的な仕様は変わっていません。仕様策定が続いていますので、最新仕様については仕様書もご確認ください。(2019.05.16)
Flexible Box Layoutでカラムレイアウト
たとえば、左右にカラム分けされたレイアウトを作りたいとします。これをCSSで実現する方法は何通りも存在します。
過去にCodeGridで紹介したような*table-cell
やinline-block
を利用したカラムレイアウトであったり、単純にfloat
を使用したものであったり、display: grid;
であったり……。
*注:これまでに紹介した記事
方法は挙げればきりがないのですが、今回はCSS Flexible Box Layout Module(以下、Flexbox)に触れたいと思います。また、今回の記事では古いシンタックスには触れず、執筆時点での最新の仕様*を元に解説していきます。
*注:執筆時点での最新の仕様
執筆者が元にした執筆時点(2015年4月上旬)での最新の仕様は、次の通りです。
- CSS Flexible Box Layout Module Level 1(Editor’s Draft, 2 March 2015)
CSS Flexible Box Layoutは文字通りレイアウトのための仕様です。CSS 2.1での仕様には、みなさんがよく知っている、次のような仕様があります。
- block layout
- inline layout
- table layout
- positioned layout
flex layoutもこれらのレイアウトモードのひとつで、より複雑なWebアプリケーションやWebページのレイアウトためにデザインされたものです。
なお、紹介するサンプルは次のリポジトリからダウンロード、またはクローンできます。併せて参照してください。
Flexible Boxサンプルリポジトリ
Flexboxを使うとどういったことができるのか
では、そのFlexboxを使うと、どんな悩みが解決されるのかを、筆者なりに考えてみました。
- 兄弟要素の高さを揃えたい
- 子要素の高さを親要素の高さにしたい
table-cell
で実装する際、position: relative;
を指定したい- カラムの順番を入れ替えたい
- 上下中央配置をしたい
これらはFlexboxを使わなくとも、実装が可能かもしれません。
たとえば、カラムの順番を入れ替えるといったことは、以前小山田が、「CSS再入門 display: tableの活用 3」で紹介した方法があります。
この方法では、display: table
を指定した要素に、direction
プロパティを使用して文章の方向を逆にすることで、カラムを入れ替えるという方法がありました。とても有用ですが、筆者的には少しトリッキーな方法に思えました。
小山田も書いているように、このプロパティは本来はアラビア語やヘブライ語といった、右から読み進めるための言語のテキストの記述方向をコントロールするためのプロパティだからです。
その振る舞いを知っていれば、「なるほど。」と理解することができるのですが、知らない場合、そこで使われているdirection
プロパティの本来の使用目的から、文章を右から始まるようにしたいのかな? と思ってしまうからです。
上下中央配置についても、古くから試行錯誤され、とてもトリッキーな手法が多く存在します。コードだけを一見しても、何をしているかが不明瞭なものが多くあります。
一方、Flexboxはレイアウトをするための仕様です。いろいろな配置がやりやすくなるメリットが注目されがちですが、それに加えて、CSSを見たとき、どういったレイアウトを作るためのコードなのかが、わかりやすくなるのもメリットだと筆者は考えています。
対応ブラウザ
対応ブラウザに触れておきます。最新のブラウザではほとんど使うことができますが、Internet Exprolerは11以降、Android 4.4以降でないと使えません。また現在でもSafariとiOS Safariには-webkit-
のベンダープリフィックスが必要です。
古いブラウザは対応しておらず、どんなサイトでも使えるとは言いがたいですが、限られた環境では優れた実装となりうることもあります。
しかしながら、正直理解しづらい仕様だと思いますので、この記事で学んでいきましょう。
フレックスコンテナとフレックスアイテム
Flexboxを攻略するには、まず2つの重要な用語を押さえる必要があります。
フレックスコンテナとフレックスアイテムという用語は、Flexboxを理解する上で、一番大事な言葉です。
display: flex;
(またはinline-flex
)が指定された要素を「フレックスコンテナ(flex container)」と呼び、その子要素を「フレックスアイテム(flex item)」と呼びます。親要素がdisplay: flex;
であれば、その子要素が自動的にフレックスアイテムとなります。
Flexboxに関連するプロパティは、名前がややこしく覚えづらいのですが、フレックスコンテナに指定できるプロパティと、フレックスアイテムに指定できるプロパティとで分けられるので、それぞれ解説していきます。
フレックスコンテナに指定できるプロパティ
まずは、フレックスコンテナとなる要素に指定できるプロパティです。
display
display
プロパティにflexもしくはinline-flexを指定することで、フレックスコンテナなります。そして、フレックスコンテナの直下の子要素が、自動的にフレックスアイテムになります。注意したいのは、孫要素はフレックスアイテムにはならないことです。
.container {
display: flex; /* or inline-flex */
}
flex-direction
フレックスアイテムを縦並び、もしくは横並びにするかどうかの配置を指定します。
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
*注:|
コード中の|
は、「いずれか(or)」という意味です。仕様書にはよく出てくる記述なので、覚えておくとよいでしょう。
それぞれのプロパティ値の意味は、次のようになります。
値 | 意味 |
---|---|
row | 初期値。ltr *の中では左から右に、rtl *の中では右から左に並びます |
row-reverse | ltr の中では右から左に、rtl の中では左から右に並びます |
column | 上から下に並びます。 |
column-reverse | 下から上に並んでいきます。 |
*注:ltr
とrtl
ltr
とrtl
は、文字表記の方向のことです。ltr
はleft to right
、rtl
はright to left
の意味で、dir属性やdirectionプロパティで使用されるキーワードです。
flex-wrap
通常、フレックスアイテムは1行にすべて収まろうとします。wrap
やwrap-reverse
を指定することで、フレックスアイテムがその行に収まりきらないときは、次の行へ折り返させることができます。また、折り返す際にどちらから始まるかも指定できます。
.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
値 | 意味 |
---|---|
nowrap | 初期値。折り返しは発生しない |
wrap | フレックスコンテナの行(または列)に、収まり切らなかった場合は、複数行(または複数列)になる。flex-direction: row; のときは、下に折り返す。flex-direction: column; のときは、文字の表記方向に従って折り返す |
wrap-reverse | フレックスコンテナの行(または列)に、収まり切らなかった場合は、複数行(または複数列)になる。flex-direction: row; のときは、上に折り返す。flex-direction: column; のときは、文字の表記方向とは逆に折り返す |
flex-direction
によるフレックスアイテムの並ぶ方向や、flex-direction
と同様に、flex-wrap
も文字の表記方向によって、フレックスアイテムの折り返す方向が変わります。それぞれの組み合わせによって、どうフレックスアイテムがどう並ぶかを図示してみました。
まずは、文字の表記方向が左から右(ltr
)になっていて、flex-direction: row;
のときと、flex-direction: column;
のときの、flex-wrapの各値を指定をした場合の図です。
図の左のflex-direction: row;
のときは、縦軸の向きを変化させ、右のflex-direction: column;
のときは横軸の向き変化させます。
次に、文字の表記方向が右から左(rtl
)の場合を見てみましょう。
フレックスアイテムは文字の表記方向にそって並びます。図の左のflex-direction: row;
のときは、縦軸の向きが変化するだけなので、特に難しくはないのですが、右のflex-direction: column;
のときは、横軸の向きが変化するため混乱しそうです。ですが、あくまで文字の表記方向にそって折り返すのか、文字の表記方向とは逆に折り返すのかの差でしかありません。
flex-flow
flex-flow
プロパティはflex-direction
とflex-wrap
のショートハンドプロパティです。初期値はrow nowrap
です。
.container{
flex-flow: <`flex-direction`> || <`flex-wrap`>;
}
justify-content
このプロパティでは、flex-direction
で指定した配置を基準にして、フレックスアイテム全体の整列を指定します。
.container {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
プロパティ値の意味は、次のようになります。
値 | 意味 |
---|---|
flex-start | flex-direction: row; のときは左揃えになり、flex-direction: column; のときは上揃えになる |
flex-end | flex-direction: row; のときは右揃えになり、flex-direction: column; のときは下揃えになる |
center | 中央配置される。 |
space-between | 均等に余白をあけるが、両端には余白を作らない |
space-around | 均等に余白をあけ、両端にも余白が作成される |
align-items
このプロパティでは、フレックスアイテムごとの整列方向をまとめて指定できます。
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
それぞれのプロパティ値の意味は、次の通りです。
値 | 意味 |
---|---|
flex-start | flex-direction: row; のときは上揃えになり、flex-direction: column; のときは左揃えになる |
flex-end | flex-direction: row; のときは下揃えになり、flex-direction: column; のときは右揃えになる |
center | 中央に揃う |
baseline | 文字のベースラインに揃える |
stretch | 高さが指定されていない場合、フレックスコンテナの高さまで広がる。またflex-flow: row wrap; などのときに、折り返す場合は、同じ行にあるフレックスアイテムの高さが同じになる |
align-content
flex-wrap
プロパティの値に、wrap
またはwrap-reverse
を指定した場合に、このプロパティは有効になります。複数行になったとき、フレックスアイテムをどのように揃えるかを指定できます。
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
それぞれのプロパティ値の意味は、次の通りです。
値 | 意味 |
---|---|
flex-start | flex-direction: row; のときは左揃えになり、flex-direction: column; のときは上揃えになる |
flex-end | flex-direction: row; のときは右揃えになり、flex-direction: column; のときは下揃えになる |
center | 中央配置される |
space-between | 均等に余白をあけるが、両端には余白を作らない |
space-around | 均等に余白をあけるが、両端にも余白が作られる |
stretch | 余白が作られないようにフレックスアイテムの大きさを調整する |
フレックスアイテムに指定できるプロパティ
フレックスアイテム自身の振る舞いを指定するプロパティがいくつかあります。
align-self
align-self
プロパティは、個々のフレックスアイテムの整列を指定することができます。基本的には上揃えで、一部の要素だけ中央揃えにしたり、下揃えにしたりといった整列をするために使用します。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
それぞれのプロパティ値の意味は、次の通りです。
値 | 意味 |
---|---|
auto | フレックスコンテナのalign-items プロパティで指定された値になる。指定されていない場合はstretch となる |
flex-start | flex-direction: row; のときは上揃えになり、flex-direction: column; のときは左揃えになる |
flex-end | flex-direction: row; のときは下揃えになり、flex-direction: column; のときは右揃えになる |
center | 中央に揃う |
baseline | 文字のベースラインに揃う |
stretch | 高さが指定されていない場合、フレックスコンテナの高さまで広がる。またflex-flow: row wrap; などのときに折り返す場合は、同じ行にあるフレックスアイテムの高さが同じになる |
order
order
プロパティは、フレックスコンテナの中のフレックスアイテムの順序を指定します。order
プロパティの値(整数)の昇順で配置されます。値が同じ要素は、ソースコード内で現れる順に配置されます。
order
はHTMLの順序を入れ替えるわけではないので、文書の意味が変わってしまう心配はありません。
.item {
order: <integer>;
}
flex-basis
フレックスアイテムの基本の長さを指定します。
そのほかのプロパティの指定値によって、設定された値の振る舞いが変わってきます。
後述するflexプロパティでflex-basis
の指定を省略した場合、値は0
が指定されます。
またauto
と指定した場合、フレックスアイテムの中身のコンテンツの大きさに依存します。
flex-direction
プロパティの値がrow
やrow-reverse
のときは、widthプロパティのように振る舞い、column
やcolumn-reverse
のときは、heightプロパティのように振る舞います。
.item {
flex-basis: <length> | auto;
}
flex-grow
フレックスアイテムが、ほかのフレックスアイテムに比べて、どれだけ伸びるかの比率です。フレックスコンテナがすべてのフレックスアイテムを収め切っても、まだ余りのスペースがある場合、各フレックスアイテムのflex-grow
プロパティに従い、自動的に利用可能な領域いっぱいまで伸びます。初期値は0
です。
.item {
flex-grow: <number>;
}
指定を見ただけでは直感的にわかりにくいのですが、おおむね次のような挙動になります。
このプロパティの詳細については、次回さらに詳しく解説します。
flex-shrink
フレックスアイテムが、ほかのフレックスアイテムに比べて、どれだけ縮むかの比率です。フレックスコンテナがflex-wrap: nowrap
で、しかも、すべてのフレックスアイテムを収めきれない場合、各フレックスアイテムのflex-shrink
プロパティに従い、ちょうど格納できるように、自動的に縮みます。初期値は1
です。
.item {
flex-shrink: <number>;
}
このプロパティも指定を見ただけでは直感的にわかりにくいのですが、おおむね次のような挙動になります。
flex-growと併せて、flex-shrinkも次回、さらに詳しく解説します。
flex
flexプロパティはflex-grow
flex-shrink
flex-basis
のショートハンドプロパティです。
flexプロパティの初期値は0 1 auto
です。
.item {
flex: none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]
}
*注:仕様の読み方
上記のコードに使われている記号は、次のような意味を持ちます。
[]
:括弧内はひとつのグループ?
:?
があるものは、省略が可能。その値がなくてもよい||
:||
の前後にあるものは、順不同で、どちらが先にきてもよい
それぞれの値は省略可能です。また、キーワードでの指定も可能です。そのような省略した書き方をした際は、自動的に決められた値に設定されます。その指定は、次のようになっています。
省略した書き方 | 実際の値 |
---|---|
flex: inherit; | flex: inherit inherit inherit; |
flex: initial; | flex: 0 1 auto; |
flex: auto; | flex: 1 1 auto; |
flex: none; | flex: 0 0 auto; |
flex: 1; | flex: 1 1 0%; |
flex: 100px; | flex: 1 1 100px; |
flex: 2 100px; | flex: 2 1 100px; |
flex: 100px 2; | flex: 2 1 100px; |
flex: 1 2; | flex: 1 2 0%; |
まとめ
今回はflexible boxの仕様にあるプロパティを一通り説明しました。まずは、それぞれのプロパティで何が設定できるのかを理解しないと、さらにそれらを組み合わせた実装は理解できません。
ですが、そのうちflex-grow
とflex-shrink
は、1行に収まるように、伸びたり、縮んだりするという概要はわかったと思いますが、どのように計算されて収まるかの計算は、やや複雑です。
次回はその2つのプロパティと取り上げて解説します。