BOOKS
by Sukeharu Kano / 狩野祐東 著書

パターンで覚えるflexbox(1)─ナビゲーションメニューの作成─

2016-04-07

 CSS3で追加された新機能の中に“flexbox”があります。名前を聞いたことがある人もいるかもしれません。でも、使ったことがある人はそんなに多くないかもしれません。

 さてこのflexbox、CSS3の新機能の中でも大物中の大物、普及すればいままでのCSSを使ったレイアウトの手法が大きく変わります。

 現在、flexboxは、IE11以降の主要なブラウザーでサポートされていて、「もうそろそろ使っていい」舞台は整っています。でも、実はW3Cが提唱している仕様がほかのCSS3の機能と比べてもユルく、ブラウザによって若干の表示上の誤差があります。また、flexbox自体が高機能でいろいろなことができるおかげで、どんなことができるのかわかりづらいところがあり、マスターしづらいのも事実。そこでこのシリーズでは、flexboxの機能自体をマスターすることよりも、典型的なデザイン・レイアウトをいくつか見ながら、「この場合はこう書いたらよい」というパターンを紹介していきます。

flexboxってなに?

 いままで、HTML/CSSのレイアウトモードには、次の4つがありました。

  1. ブロック・レイアウトモード──<div>など、display:block;が指定されたボックスのレイアウトモード(レイアウトの規則)です。もっとも標準的なHTML/CSSのレイアウトモードです。
  2. インライン・レイアウトモード──テキストや、<strong>などdisplay:inline;が指定された要素のレイアウトモードです。
  3. テーブル・レイアウトモード──テーブルのレイアウトモードです。
  4. ポジション・レイアウトモード──CSSのpositionを使用したレイアウトモードです。座標を指定して、絶対的な位置でボックスを配置します。
  5. flexboxレイアウトモード──新しいボックスの配置方法です。ごく大雑把にいえば、次のようなことができるようになります。
    • ボックスを配置するための新しいレイアウトモード
    • ボックスを横・縦に並べることができる(floatの代わりに使える)
    • 子要素の幅や高さを自動的に伸縮させて、子要素を親要素のスペースにぴったり収めることができる

 flexboxは、いままでの4つのレイアウトモードに比べても高機能で、ここに挙げた以外にも自在なボックスのレイアウトができますが、はじめから全体像を把握しようとするとかなり複雑です。そこで、今回の記事は、ちょっとずつflexboxに慣れることができるように、複数回に分けて典型的な使い方の例を紹介します。

flexboxでナビゲーションを作成する

 flexboxでまず最初に取り組めるのは、Webページのナビゲーションの作成でしょう。ナビゲーションは、flexboxの基本的な機能のみを使って実現することができます。

flexboxの基本機能:ボックスを横に並べる

 ボックスを横に並べるのはflexboxのもっとも基本的な機能のひとつです。この基本機能を使って、<li>を横に並べてナビゲーションを作成します。floatを使うよりもずっと簡単だと感じることでしょう。

 ナビゲーションは、これまでは<ul><li>floatを使って実現していました。floatの代わりにflexboxを使うとより少ないCSSの行数で書くことができて、しかも柔軟なレイアウトが可能です。まずは基本的なナビゲーションを作ってみましょう。

 HTMLはこのとおり。

<nav class="regular">
	<ul>
		<li><a href="home.html">Home</a></li>
		<li><a href="about.html">About</a></li>
		<li><a href="web.html">Web Design</a></li>
		<li><a href="column.html">Column</a></li>
	</ul>
</nav>

 CSSはこのようにします。flexboxの部分にはマーカーを付けてあります。

body {
	font-family: sans-serif;
}
nav {
	background-color: #222222;
	color: white;
}
nav ul {
	display: flex;
	flex-flow: row;
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
nav a {
	display: block;
	border-radius: 4px;
	padding: 12px 24px;
	color: white;
	text-decoration: none;
}
nav li a:hover {
	background-color: #8cae47;
}

 このように、CSSに2行書くだけで、各<li>が自動的に、左揃えで横に並んでくれます。floatと違って<li>の幅を指定する必要もないし、親要素(<ul>)でフロート解除をする必要もありません。

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

ナビゲーションを右揃えにする

 次に、左揃えだったナビゲーションを右揃えにしてみます。<ul>のCSS(display:flex;を書いているのと同じところ)に1行追加するだけです。HTMLに変わりはありません。

...
nav ul {
	display: flex;
	flex-flow: row;
	justify-content: flex-end;
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
...

 結果はこちら。

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

ナビゲーションを中央揃えにする

 ナビゲーションの各リンクを中央揃えにするには、justify-contentの値をcenterにするだけです。

...
nav ul {
	display: flex;
	flex-flow: row;
	justify-content: center;
	
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
...

はい。中央揃えになりました。

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

ナビゲーションのリンクを均等配置にする

 ここまで、ナビゲーションの各リンクを左揃え、右揃え、中央揃えにしてきました。flexboxではさらに、これらリンクの<li>を、親要素の<ul>のスペースをいっぱいに使って均等に配置することもできます。

...
nav ul {
	display: flex;
	flex-flow: row;
	justify-content: space-around;
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
...

 結果はこちら。

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

ここまでのまとめ

 ここまで、flexboxレイアウトモードを使うために、3つのCSSを使ってきました。ここで簡単に、いままで使ってきたCSSの機能と役割を紹介しておきます。

display:flex;

 display自体は前からあるCSSです。flexboxレイアウトモードで要素を配置するには、まず、親要素に「display:flex;」を指定します。これが「子要素はflexboxレイアウトモードでボックスを配置するよ」という宣言になります。ナビゲーションの場合、flexboxレイアウトモードを使って各リンク項目の<li>を横に並べたいので、その親要素──<ul>──に「display:flex;」を指定している、というわけです。

display:flex;

flex-flow

 また、display:flex;を指定した親要素には「その子要素をどうやって配置するか」を指定する各種CSSプロパティを追加することができます。flex-flowはそうした子要素の配置方法を指定するCSSのひとつで、「flex-flow:row;」とすると、ボックスが横一列に並ぶようになります。flex-flowには、子要素を横に並べるrowのほかに、縦に並べるcolumnなどがありますが、row以外のものについてはまた後で紹介します。ちなみに、flexboxレイアウトモードで配置される子要素のことを「flexアイテム」と呼びます。

flex-flow: row;

justify-content

 さらに、flex-flow:rowで横に並んだ子要素(flexアイテム)を、左揃えや右揃えなどに配置するには、justify-contentを使います。justify-contentも、display:flex;を指定した要素に指定します。

justify-content: flex-start; /* 子要素を左揃えにする(例では使っていません) */
justify-content: flex-end; /* 子要素を右揃えにする */
justify-content: center; /* 子要素を中央揃えにする */
justify-content: space-around; /* 子要素を均等配置にする */

左右に分けて配置する

 flexboxでは、flexアイテムを左右に分けて配置することもできます。たとえば、このナビゲーションに「log in」という項目が1つ増えたとします。この「log in」だけナビゲーションの右側に配置し、ほかの各リンク項目は左揃えにすることもできます。

 HTMLには1つ<li>を追加します。追加した<li>にはclass="login"と、class属性をつけておきます。

<nav>
	<ul>
		<li><a href="home.html">Home</a></li>
		<li><a href="about.html">About</a></li>
    		<li><a href="web.html">Web Design</a></li>
		<li><a href="column.html">Column</a></li>
		<li class="login"><a href="login.html">log in</a></li><!-- 追加 -->
	</ul>
</nav>

 CSSはこのとおり。最も基本的な、ナビゲーションを左揃えに配置するCSSをベースにしています。追加した部分にはマーカーをつけてあります。

body {
	font-family: sans-serif;
}
nav {
	background-color: #222222;
	color: white;
}
nav ul {
	display: flex;
	flex-flow: row;
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
nav li.login {
  margin-left: auto; 
}
nav a {
	display: block;
	border-radius: 4px;
	padding: 12px 24px;
	color: white;
	text-decoration: none;
}
nav li a:hover {
	background-color: #8cae47;
}

 実際に表示してみると「log in」と、そのほかのリンクが左右に分かれて配置されているのがわかります。

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

ボックスを縦に並べる

 ここまで、flexアイテムを横に並べるテクニックをいろいろ紹介してきましたが、縦に並べることも簡単です。そこで、ナビゲーションを左揃えに配置するHTML/CSSをベースにして、スマートフォンのハンバーガーメニューのように、各リンクを縦に並べてみます。

 HTMLには<li>をひとつ追加して、そのリンクテキストとしてを追加します(FontAwesomeを使用)。また、追加した<li>にはclass="hamburger"と、class属性をつけておきます。

<nav>
	  <ul id="menu">
		<li class="hamburger"><a href="#menu"><i class="fa fa-bars"></i></a></li>
		<li><a href="home.html">Home</a></li>
		<li><a href="about.html">About</a></li>
    		<li><a href="web.html">Web Design</a></li>
		<li><a href="column.html">Column</a></li>
	  </ul>
</nav>

 CSSは、ナビゲーションを横に並べていた「flex-flow:row;」の「row」を「column」にするだけ。こうすることで、横に並んでいたflexアイテムが縦に並ぶようになります。変更箇所にはマーカーをつけてあります。

...
nav ul {
	display: flex;
	flex-flow: column;
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
...

 表示結果はこちら。

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

ハンバーガーだけ右揃えにする

 さてここで、ハンバーガーだけ右揃えにしたい場合は、<li class="hamburger">に、align-selfという、flexbox関連のCSSを適用します。align-selfは、flexアイテムの行揃えを個別に指定するためのCSSで、ここではその値をflex-end、右揃えにしています。

...
nav ul {
	display: flex;
	flex-flow: column;
	margin: 0;
	padding: 6px;
	list-style-type: none;
}
nav li.hamburger {
  align-self: flex-end; 
}
nav a {
	display: block;
	border-radius: 4px;
	padding: 12px 24px;
	color: white;
	text-decoration: none;
}
nav li a:hover {
	background-color: #8cae47;
}

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

ここまできたら…レスポンシブ!

 ここまで来たら、当然レスポンシブデザインにしたいですよね。基本的には、画面サイズが小さいときはflex-flowを「column」に、大きければ「row」に切り替えるだけでOKです(もちろんハンバーガーは隠します)。例ではわかりやすいようにブレイクポイントを550pxに設定してあります。ブラウザウィンドウを広げたり狭めたりして試してみてください。

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

狩野 祐東

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

BOOKS by 狩野祐東