BOOKS
by Sukeharu Kano / 狩野祐東 著書

パターンで覚えるflexbox(4)─flexboxの応用例─

2016-04-27

 ここまで第1回第2回第3回と、flexboxの機能をいろいろと紹介してきました。実際に使われそうなケースを紹介してきて、おそらくこれだけできれば大体のことはこなせると思います。

 ところがこれで終わらないのがflexbox。最後にボックス配置の応用例として、2つの例を紹介します。

応用例1:多数のボックスをタイル状に配置する

 1番目の応用例として、多数のボックスをタイル状に配置してみます。いままで、flexアイテムは2か3つくらいでしたが、もっと多くのボックスを並べてみます。

 第2回で紹介したサンプルのHTMLを編集して、子要素(<div class="flex-item">〜</div>)を8個に増やします。

<div class="flex-container">
	<div class="flex-item">
		    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut nisl mi.</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 amet ipsum. Aenean eget tempor leo. Nunc velit tellus, maximus vel imperdiet ac, dignissim sed enim.</p>
		    <button class="detail">SHOW DETAIL</button>
	</div>
    <div class="flex-item">
		    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut nisl mi.</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 amet ipsum. Aenean eget tempor leo. Nunc velit tellus, maximus vel imperdiet ac, dignissim sed enim.</p>
		    <button class="detail">SHOW DETAIL</button>
	</div>
    <div class="flex-item">
		    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut nisl mi.</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 amet ipsum. Aenean eget tempor leo. Nunc velit tellus, maximus vel imperdiet ac, dignissim sed enim.</p>
		    <button class="detail">SHOW DETAIL</button>
	</div>
    <div class="flex-item">
		    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut nisl mi.</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 amet ipsum. Aenean eget tempor leo. Nunc velit tellus, maximus vel imperdiet ac, dignissim sed enim.</p>
		    <button class="detail">SHOW DETAIL</button>
	</div>
</div>

 CSSは第2回のサンプルのままです。

body {
  font-family: sans-serif;
}
.flex-container {
  display: flex;
  flex-flow: row;
  outline: 1px dotted #ff8624;
}
.flex-item {
  flex: 1 1 auto;
  margin: 0 8px;
  padding: 10px;
  width: 200px;
  background-color:  #e5e5e5;
}
.detail {
  margin: 0;
  border: none;
  border-radius: 6px;
  padding: 12px 0;
  width: 100%;
  font-size: 16px;
  text-align: center;
  color: #fff;
  background-color: #8cae47;
}

 このCSSだと、なんともしても1行に収めようとするために、各flexアイテムの幅は狭くなります。

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

 これでは大変見づらいので、1行に4つボックスが並ぶように変更します。変更した部分はマークしています。

...
.flex-container {
  display: flex;
  flex-flow: row wrap;
  outline: 1px dotted #ff8624;
}
.flex-item {
  flex: 1 0 20%;
  margin: 0 8px 8px 0; /* 下マージン8pxを追加 */
  padding: 10px;
  /* width: 200px; このwidthはコメントアウト */
  background-color:  #e5e5e5;
}
...

 表示結果はこのようになります。ボックスが横に4つ、2行で並ぶことになります。

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

flex-flowの2番目の値

 変更したCSSにはいくつか注目すべきポイントがあります。ひとつはflex-flowの値。flex-flowには、ボックスを横に並べる「row」、縦に並べる「column」のほかに、半角スペースで区切って2番目の値を指定することができます。それが今回指定した「wrap」です。2番目の値を「wrap」にすると、親要素に入りきらないflexアイテムを改行して表示させることができます。

 2番目の値は、wrapのほかに「no-wrap」があります。2番目の値をno-wrapにすると、flexアイテムは改行されずに1行で収まるようになります。

flexの値に注目

 「flex-flow: row wrap;」とすることで、親要素に入りきらないflexアイテムは改行して表示させるように変更できました。あとは、各flexアイテムを横に4つ、ピッタリサイズで並ぶように幅を伸縮できるように変更すればよいのです。そのためにflexの値を修正して、このようにしてあります。

flex: 1 0 20%;

 これがすべてのflexアイテムに適用されています。

 このflexに指定されている意味を考えてみましょう。このflexの値により、各flexアイテムのサイズ(幅)は次のように決定されます。

  1. flexの1番目の値が「1」なので、親要素と子要素の間に空きスペースがあったら、すべての子要素が均等に伸びる
  2. flexの2番目の値が「0」なので、子要素は縮まらない
  3. 各flexアイテムの基準サイズ(幅)は、flexの3番目の値により、親要素の幅の20%になる

 ここで、各flexアイテムには右マージンに8pxが指定されています(下マージンも指定していますが、ここでは右マージンだけ注目してください)。

margin: 0 8px 8px 0

 マージン、ボーダー、パディングは、flexboxの伸縮対象にはなりません。伸縮するのはあくまでwidthheightだけです。各flexアイテムに8pxの右ボーダーがかかっている以上、このflexアイテムを横に4つ並べるには、各ボックスの幅が、親要素の25%(つまり親要素の幅の1/4)以下になる必要があります。そこで、flexアイテムの基準幅(flexの3番目の値)を、25%ではなく20%にしています。

flexアイテムには8pxの右マージンがかかっている
flexアイテムには8pxの右マージンがかかっている

 幅が20%+右マージン8pxで、仮にflexアイテムが伸びも縮みもしない場合、おそらく親要素と子要素の間に多少空きスペースが空くはずです。しかしこの空きスペースは、もうひとつflexアイテムが入るほどではないので、flexアイテムは改行し、空きスペースは空きスペースのまま残ります。

幅が20%で、flexアイテムが伸びも縮みもしない場合、親要素に空きスペースが空く
幅が20%で、flexアイテムが伸びも縮みもしない場合、親要素に空きスペースが空く

 ここで、flexの1番目の値を「1」にすることにより、「空きスペースがあったら、すべての子要素が均等に伸びる」ようにしています。こうすることで、flexアイテムが親要素にピッタリ収まるサイズの幅になります。

flexアイテムが均等に伸びて、親要素にピッタリ収まるサイズになる
flexアイテムが均等に伸びて、親要素にピッタリ収まるサイズになる

 これで、「8つのボックスを、4列2行で並べる」ことができるようになります。

応用例2:入れ子のflexbox─下にあるボタンの位置を揃える─

 4列2行で並べたflexアイテムには、それぞれ「SHOW DETAIL」と書かれたボタンがあります。このボタンを、ボックスの下に配置して揃えてみます。そのために、いままで「flexアイテム」といっていた子要素(<div class="flex-item">)にも「display: flex;」を適用して、その子要素もflexboxモードで配置されるようにします。そして、ボタンのmargin-topに「auto」を指定することで、ボタンがボックスの下部に整列するようになります。

...
.flex-container {
  display: flex;
  flex-flow: row wrap;
  outline: 1px dotted #ff8624;
}
.flex-item {
  flex: 1 0 20%;
  margin: 0 8px 8px 0;
  padding: 10px;
  
  display: flex;
  flex-flow: column;
  
  background-color:  #e5e5e5;
}
.detail {
  margin: 0;
  margin-top: auto;
  border: none;
  border-radius: 6px;
  padding: 12px 0;
  width: 100%;
  font-size: 16px;
  text-align: center;
  color: #fff;
  background-color: #8cae47;
}

 各ボックスの下部にボタンが配置され、見た目にもスッキリしました。

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

Flexboxを取り上げている関連書籍

わたしが書いた本の中では、『HTML5&CSS3デザインレシピ集』『いちばんよくわかるHTML5&CSS3きちんと入門』で、Flexboxを詳しく取り上げています。このサイトの書籍紹介ページでは、これらの本に掲載されているサンプルも確認することができます。

HTML5&CSS3デザインレシピ集

いちばんよくわかるHTML5&CSS3きちんと入門

狩野 祐東

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