BOOKS
by Sukeharu Kano / 狩野祐東 著書

パターンで覚えるflexbox(2)─ボックスを横に並べる─

2016-04-13

 前回の記事「パターンで覚えるflexbox(1)─ナビゲーションメニューの作成─」では、flexboxを使ってナビゲーションメニューを作成しました。flexboxには、ボックス(flexアイテム)を横や縦に並べるだけでなく、それらを「親要素のスペースに合わせて子要素(flexアイテム)を伸縮させてピッタリ収める」という、驚きで強力な機能があります。今回は、その驚きで強力な機能を使ってボックスを配置してみましょう。

2つのボックスを横に並べる

 まずは簡単な例として、2つのボックスを横に並べてみます。

HTMLとCSSを用意する

 まずはこんなHTMLを用意します。親要素(<div class="flex-container">〜</div>)の中に、子要素(<div class="flex-item">〜</div>)が2つ入っている状態です。

...
<div class="flex-container">
	<div class="flex-item">
		    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...</p>
    	    <button class="detail">SHOW DETAIL</button>
  	</div>
  	<div class="flex-item">
		    <p>Vivamus ac velit ac ante lacinia malesuada. Donec sit amet neque ac orci gravida placerat in sit ...</p>
		    <button class="detail">SHOW DETAIL</button>
	</div>
</div>
...

 この2つの<div class="flex-item">〜</div>を横に並べるには、親要素の<div class="flex-container">〜</div>に、次のようなCSSを適用します。flexboxの機能の部分にはマーカーをつけています。

...
.flex-container {
  display: flex;
  flex-flow: row;
}
.flex-item {
  border: 1px solid #fff;
  padding: 10px;
  background-color: #e5e5e5;
}
...

 このように表示されます。

See the Pen Basic flexbox by Sukeharu Kano (@deinonychus) on CodePen.

 2つのボックスが横に並ぶだけでなく、高さも揃っているのに気づきましたか? 横に並ぶボックスの高さを揃えるというのは、いままでのfloatでは、汎用性の低い裏技的なテクニックを使わない限り実現できませんでした。横に並んだボックスの高さが揃うというのも、flexboxの強力な機能のひとつです。

 では、なぜ高さが揃うのでしょう? それは、flexboxレイアウトモードが、親要素のスペースに合わせて、子要素(flexアイテム)を伸縮させてピッタリ収めるようになっているからです。flexアイテムは、幅も高さも、親要素のスペースにピッタリ収まるように伸縮するわけですね。

2つのボックスの幅を指定する

 しかし、このままの状態では、右側のボックスが大きくなってしまっています。右側のボックスのほうがテキストが長く、コンテンツ量が多いからです。そこでまずは、両方のボックスに同じ幅を指定してサイズを揃えることにします。ついでに、くっつかないようにマージンも設定しましょう。それには、flexアイテムにwidthmarginを設定します。

...
.flex-item {
  margin: 0 8px;
  padding: 10px;
  width: 200px;
  background-color:  #e5e5e5;
}
...

 結果はこのとおり。

See the Pen Basic flexbox 2 by Sukeharu Kano (@deinonychus) on CodePen.

 この例の一番外側の点線は、親要素<div class="flex-container">〜</div>が確保しているスペースです。また、CSSで2つの子要素のボックスの幅は200pxに指定しています。見ている端末の画面サイズにもよりますが、このページをPCまたはタブレットで見ていれば(=十分に広い画面サイズで見ていれば)、子要素のボックスの右側に空きスペースができているはずです。

親要素と子要素の間にすきまが空いている
親要素と子要素のあいだの空きスペース

空きスペースを調整する“flex”

 この空きスペースを埋めるのに使うのが“flex”です。flexアイテム(<div class=”flex-item”>〜</div>)に、新たにこのようなCSSを追加します。

.flex-item {
  flex: 1 1 auto;
  margin: 0 8px;
  padding: 10px;
  width: 200px;
  background-color:  #e5e5e5;
}

 flexを追加した結果、flexアイテムが横方向に伸びることによって、親要素と子要素の間にできていた空きスペースが埋まります。

See the Pen Basic flexbox 3 by Sukeharu Kano (@deinonychus) on CodePen.

 いまflexボックスのCSSに追加したflexは、子要素(flexアイテム)を親要素のスペースにピッタリ収めるために、flexアイテムを伸縮させる方法を決めるものです。flexには3つの値を指定します。

子要素が親要素よりも大きい場合、最初の値で「伸びる量」が決まる

 flexの最初の値には、親要素の領域よりも子要素(flexアイテム)が小さい場合に、空きスペースを分配する割合を数値(単位なし)で指定します。この例の場合、2つのボックスともにflex: 1 1 auto;が指定されていることになりますから、最初の値はどちらのボックスにも「1」が指定されていることになります。そのため、親要素との間にできた空きスペースは、2つのflexアイテムに1:1で分配されます。その結果、2つのボックスは横方向に均等に引き伸ばされます。

flexの最初の値には、この空きスペースを分配する割合を指定する
空きスペースは1:1で分配される

 ちなみに、flexの最初の値が0なら、空きスペースの分配率が0になりますから、ボックスは引き伸ばされません。値を0にすると伸縮しないというのはけっこう重要で、コラムレイアウトを作るときなどに重宝します。

逆に子要素が親要素よりも大きい場合、2番目の値で「縮む量」が決まる

 それではflexの2番目の値を理解するために、2つのボックスの幅を両方とも500pxにしてみましょう。いったんflexも「1 0 auto」にしておきます。

...
.flex-item {
  flex: 1 0 auto;
  margin: 0 8px;
  padding: 10px;
  width: 500px;
  background-color:  #e5e5e5;
}
...

子要素の幅が大きすぎるために、親要素からはみ出して横に並びます。floatと違ってflexboxの場合、親要素よりも子要素の方が大きかったら、親要素のスペースを無視してでも子要素が横に並びます。

See the Pen Basic flexbox 4 by Sukeharu Kano (@deinonychus) on CodePen.

 それではflexの2番目の値を「1」にします。

...
.flex-item {
  flex: 1 1 auto;
  margin: 0 8px;
  padding: 10px;
  width: 500px;
  background-color:  #e5e5e5;
}
...

 こうすることで、親要素からはみ出た子要素の幅は、2つのボックスに1:1で分配され、その分だけ縮小されます。

flexの2番目の値には、はみ出た量を分配する割合を指定する
親要素からはみ出た量 flexの2番目の値で各子要素に分配される

 こちらが実際の動作例。親要素からはみ出た分量が2つの子要素に1:1で分配され、親要素にピッタリ収まるように縮小されています。

See the Pen Basic flexbox 5 by Sukeharu Kano (@deinonychus) on CodePen.

3番目の“auto”はどういう意味?

 flexの3番目の値には、拡大も縮小もされなかったときのflexアイテムのサイズを指定します。この3番目の値には、autocontent、または幅を指定します。この記事では3番目の値をautoにしていますが、flexアイテムに幅を指定する必要がある場合──つまりwidthを書いておく必要がある場合──、そのwidthに指定する値をautoの代わりに書いておくことができます。詳しくは第3回の記事で取り上げますが、よくわからないうちは、flexアイテムにwidthを指定し、3番目の値はautoにしておいてよいでしょう。

ボックスによって分配率を変えると

 ここまで、親要素に空きスペースがあるときの子要素の拡大も、子要素がはみ出たときの縮小も、2つの子要素の間で同率になるよう分配してきました。それでは最後に、この分配率を3:1に変えてみます。わかりやすいように子要素の幅を200pxに戻して、子要素が拡大するようにします。

 それから、HTMLのほうで、2つのボックスに対しitem1、item2というクラスを追加します。そして、いままでのflex:1 1 auto;をコメントアウトし、item1、item2の拡大率が3:1になるように、それぞれにflexを指定しています。HTMLやCSSのソースは、[HTML][CSS]をクリックすると確認できます。

See the Pen Basic flexbox 6 by Sukeharu Kano (@deinonychus) on CodePen.

 CodePenでソースコードを書き換えることができるので、flexwidthの値をいろいろ変えて試してみてください。CodePenロゴをクリックすると、別ウィンドウでソースのサンプル例だけを表示させることもできます。

狩野 祐東

Web/アプリケーションUIデザイナー、エンジニア。執筆家。 アメリカ・サンフランシスコに留学、UIデザイン理論を学ぶ。Webサイトやアプリケーションのデザイン・開発、関連技術書籍の執筆を数多く手がける。株式会社Studio947代表。

BOOKS by 狩野祐東