よこ並びのCSS。
フレキシブルボックスレイアウトでよこ並び
floatプロパティは要素を左右に寄せるためのプロパティだし、displayプロパティのtable
は、テーブル(表)をレイアウトするための値だし、inline-block
はあくまでブロック要素だし、どれも特別にナビゲーションをよこ並びするためのプロパティというわけではありませんでした。
けれどもフレキシブルボックスレイアウトは、指定した要素の大きさを柔軟に伸縮させ、画面サイズに対して最適な大きさで表示させるために用意された値で、まさにこのナビゲーションのために用意された値なんですよね!要素を柔軟にレイアウトするための仕様なんです。
フレキシブルボックスの特徴
フレキシブルとは、“柔軟性がある様子”のこと。具体的には、displayプロパティでflex
という値を指定することで、その要素でフレキシブルボックスが利用可能になります。
ちょっとだけtable/table-cellの仕組みと似てて、display: flex
と指定した要素自体がよこ並びになるわけではなくて、flex
と指定した要素の直接の子要素が、よこ並びされる対象となります。ただ、table-cellみたく、特別にCSSを指定する必要はなくて、親要素にdisplay: flex
と指定した子要素は勝手によこ並びになるので、ちょっと不思議な感じですよね。
ul {
list-style: none;
display: flex;
margin: 0;
padding: 0;
text-align: center;
background: #fafafa;
}
さぁ、もうすでに上のli要素はすべてフレキシブルな要素となっています。フレキシブルボックスレイアウト用に用意された様々なプロパティを使うことで、思い通りのレイアウトが可能となります:D。
display: table
と指定することで、div要素が突如table要素さながらとなったように、display: flex
と指定した要素は、唐突にフレキシブルな要素に様変わりします。
テーブルはつまり表なレイアウトなのでわかりやすかったですが、フレキシブルボックスはいままで出会ったことのないレイアウト方法なので、なかなか慣れないですけれど、大きく以下のような特徴があります。
displayプロパティでflex
と指定した要素は、「コンテナ」と呼ばれるようになります。
そして、コンテナの直接の子要素はすべて「アイテム」と呼ばれ、フレキシブルボックスレイアウト関連のプロパティの初期値によって、すべてよこ並びでレイアウトされます。
要素が並ぶ進行方向となる軸を「主軸」、それに直角な方向の軸を「交差軸」と呼びます。

フレキシブルボックスについて、詳しくは下記ページを参照のこと。
CSS flexible box の利用 - CSS: カスケーディングスタイルシート | MDN
ナビゲーションを中央に配置する
要素を中央に配置するには、justify-contentプロパティを使います。このプロパティは、アイテムの配置の仕方を調整するためのプロパティになります。ここではcenter
という値を指定しています。
ul {
list-style: none;
display: flex;
justify-content: center;
⋮
ボタンのサイズを揃える
アイテムの横幅を制限するにはflex-basisプロパティを使います。下のサンプルでは、10em
に指定しています。文字数によって改行したボタンの大きさが揃わないのは、フロートやテーブルの時と同じですね…。
li {
flex-basis: 10em;
}
縦方向の位置を制御するには、テーブルやインライン・ブロックの時にはvertical-alignプロパティを使いましたが、フレキシブルボックスではフレキシブルボックス専用のalign-itemsプロパティを使います。ここでは中央に揃えるためalign-items: center
を指定しています。※middle
じゃないので注意です。
これまたテーブルやインライン・ブロックの時と同様、字面的には中央に揃えど、ボタンのサイズは揃わぬままです…。
ul {
list-style: none;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
text-align: center;
background: #fafafa;
}
そこで、li要素だけじゃなく、a要素と、さらにその中のテキストもフレキシブルに扱えるように、li要素とa要素にもdisplay: flex
を指定しちゃいます!つまり、li要素もa要素も、アイテムでありコンテナになるということ。
さらに、justify-contentプロパティも同じくli要素、a要素にも指定して、flex-basisプロパティも、li要素、a要素に、同じく10em
を指定します。
ここまでの指定で、ボタンの大きさが揃いました。align-itemsプロパティは、初期値としてstretch
という値が指定されるため、特に何も指定しなければ、アイテムは交差軸(縦方向)の端から端まで埋まった状態になるんですね:D。
ul {
list-style: none;
margin: 0;
padding: 0;
text-align: center;
background: #fafafa;
}
ul, li, li a {
display: flex;
justify-content: center;
}
li, li a {
flex-basis: 10em;
}

a要素にdisplay: flex
を指定したことで、a要素の子要素がアイテムになるわけですが、a要素には子要素がないですよね…。そんな場合には、その中のテキストが、無名の要素ってことで、アイテムとして扱われることになっています:D。
a要素にalign-itemsプロパティでcenter
と指定すれば、そのアイテムとなるテキストが上下中央に配置されるはずです。
li a {
cursor: pointer;
align-items: center;
padding: 1em;
}

横幅いっぱいに広げる
横幅いっぱいに広げるには、アイテムに対して、flex-growプロパティで1
以上の数値を指定します。
ここで指定した数値は、コンテナ内の余った領域を、各アイテムにどう分配するかの割合を表します。ここではアイテム全てに対して1
を指定しているので、アイテムそれぞれに同じ分ずつ余白が分配されることになります。
きちんと分配しているので、table-cellよりも、アイテムのバランスがよいのがわかりますね。
li, li a {
flex-grow: 1;
}

レスポンシブにする
そして、スマホではたて並びになるようにしましょう。テーブルやインライン・ブロックの時と同じように、フレキシブルにしてる要素をdisplay: block
に指定するでもよいんですが、せっかくフレキシブルなので、flex-directionプロパティを使って並びの向きを変えることにします。
ul要素にflex-direction: column
と指定すれば、たて並びになります。あと、パディングの向きも変えたらできあがり。
@media screen and (max-width: 767px) {
ul {
flex-direction: column;
}
li:nth-child(n+2) {
padding: 1px 0 0;
}
}
フレキシブルボックスで商品一覧
ul要素に、displayプロパティでflex
とすれば、ul要素がコンテナ、li要素がアイテムとして、フレキシブルボックス関連のプロパティで扱えるようになるんでしたね。
.itemlist {
list-style: none;
display: flex;
max-width: 1024px;
margin: 0 auto;
padding: 0;
}
早速、li要素が横並びになりましたが、全部一列で並んじゃいましたー!ちゃんと均等に並んでるからテーブルよりは綺麗だけれども…:(。
※つまり、フレキシブルボックスのアイテムにはwidthプロパティは無効ということ…。
アイテムを改行させるには、専用のflex-wrapプロパティを使って、改行する旨を指定せねばなりません。初期値がnowrap
で、改行しないことになってるんです。flex-wrap: wrap
と指定すれば、うまく改行するようになりました。
.itemlist {
list-style: none;
display: flex;
flex-wrap: wrap;
⋮
レスポンシブにする
あとはレスポンシブに列を切り替える指定ですが、フレキシブルボックスならではの、便利な指定方法があるので、そちらを使ってみます!
指定するスタイルはひとつ、flexプロパティだけ。displayプロパティの値のflex
とはまた別の、「flex」というプロパティ名になります。
flexプロパティは、アイテムの伸縮率を決めるためのプロパティで、実はこのプロパティ、ひとつめの値がflex-growプロパティ、ふたつめの値がflex-shrinkプロパティ、みっつめがflex-basisプロパティを指定することになっていて、3つのプロパティをまとめて指定するためのショートハンドプロパティになってるんです。それぞれの値を、半角スペースで区切って指定します。
.itemlist li {
flex: 1 1 300px;
padding: 10px;
box-sizing: border-box;
}
ここでは、1 1 300px
と指定しました。コンテナの余った領域を均等に割り振って、アイテムの横幅を300pxに制限するってことです。下のサンプルの画面サイズを縮めていくと、アイテムの横幅が300px以下になるタイミングで勝手に改行するのがわかります。
ただ、ちょっと改行するのが早いかなーとも感じますね…。1列になった時の商品が大きすぎるので、flex-basisプロパティの値をもっと少し小さく、200px
にしてみます。これで、1列になる時のアイテムの横幅は、399pxになるはずです。
.itemlist li {
flex: 1 1 200px;
padding: 10px;
box-sizing: border-box;
}

横幅が狭い時は良い感じなんですけれど、200pxまで小さくなれるようになったため、横幅が1000pxの時には5つ並べるってことになってしまったんですね…!しかも最後のアイテムはコンテナの余った領域を独り占めしちゃって大変なことになってます…X(。
そこで、アイテムにはmin-widthプロパティで33.333333%
と指定して、3分の1以下にはならないように指定します。
.itemlist li {
flex: 1 1 200px;
min-width: 33.333333%;
padding: 10px;
box-sizing: border-box;
}
うむ、落ち着いたかな…。
しかし!7つめの商品を追加した途端、やっぱり最後の商品だけ大変なことに…。
3分の1以下にならないようにするだけじゃなくて、3分の1以上にもならないようにしなきゃダメか…。
.itemlist li {
flex: 1 1 200px;
min-width: 33.333333%;
max-width: 33.333333%;
padding: 10px;
box-sizing: border-box;
}
いや、3分の1以上にならないということはずっと3分割ということだから意味ないですね…X(。
ということで結局、以下のように指定することに…。
flexプロパティはやめて、flex-basis
の値だけ33.333333%
に指定しました。もう拡張はしません。そして、メディアクエリを使って、flex-basisプロパティの値を、横幅が767px以下の時には50%
、414px以下の時には100%
と切り替えることで、落ち着きました:D。あまりフレキシブルの良いところを活かせてないかも…。
.itemlist li {
flex-basis: 33.333333%;
padding: 10px;
box-sizing: border-box;
}
@media screen and (max-width: 767px) {
.itemlist li {
flex-basis: 50%;
}
}
@media screen and (max-width: 414px) {
.itemlist li {
flex-basis: 100%;
}
}
IE11にも対応する
…と思いきや、IE11では下図のように、レイアウトが崩れちゃってました…!
横幅が広くても2列で改行しちゃってます。Can I use...にも大量のバグが存在する
とありますね!

li要素に指定している、box-sizing: border-box
が効いてないみたいです…X(。
ここの指定を、content-box
にすると、flex-basis
の値も修正しないといけないですけれど、IE11でもちゃんと表示されるようになります。
.itemlist li {
flex-basis: calc(33.333333% - 20px);
padding: 10px;
box-sizing: content-box;
}
@media screen and (max-width: 767px) {
.itemlist li {
flex-basis: calc(50% - 20px);
}
}
@media screen and (max-width: 414px) {
.itemlist li {
flex-basis: calc(100% - 20px);
}
}
border-box
のままにしときたい場合は、横幅をmax-widthプロパティで指定すれば、border-box
がちゃんと反映されるんですけれど、そうとなるともう、flex-basisプロパティの指定はいらなくなりますね…¦(。
.itemlist li {
max-width: 33.333333%;
padding: 10px;
box-sizing: border-box;
}
@media screen and (max-width: 767px) {
.itemlist li {
max-width: 50%;
}
}
@media screen and (max-width: 414px) {
.itemlist li {
max-width: none;
}
}
おわりに。
ナビゲーションと、商品一覧というシチュエーションをいろんな方法でよこ並びしてきましたが、どの方法も一長一短だなぁと感じました。長らくフロートでよこ並びしてきたこともあって、フロートの方が馴染みがあるのだけれど、やはりフレキシブルボックスの方が柔軟性はある感じ。けど今の所は「便利なテーブル」くらいの感覚かな…¦(。もっと小慣れてきたらもっと便利に感じるんだと思います;D。それに、フレキシブルボックスレイアウトはよこ並びだけじゃないですものね!
他にもこんな使い方があるよ!とか、フレキシブルボックスとはそもそも…などありましたら、ぜひ教えてくださいー。また、記事の中で、間違った使い方や、間違った説明してるところがあったらどしどしご指摘いただけると嬉しいです!
以上、「よこ並びのCSS。」でした!最後まで読んでいただきありがとうございますXD!
引用・参考文献
Comment & Pingback