WEB【実例あり】2017年の横並びレイアウトCSSはこれで決まり!【決定版】

【実例あり】2017年の横並びレイアウトCSSはこれで決まり!【決定版】

※本記事は2016年2月14日に公開された記事を一部加筆・修正しています。

あけましておめでとうございます。
最近朝ジョナにハマってます山田でございます。

横並びレイアウトのジレンマ

Web制作では毎度毎度お世話になる横並びレイアウトちゃんですが、floatにしろinline-blockにしろtable-cellにしろ、横並びを実現するための色々な方法が巷では語られているものの、それぞれ一癖も二癖もあって扱いづらいのはみなさんご存知の通りです。

ということで、この度は僭越ながら2017年の横並びレイアウトCSSをこの場を借りまして決定させていただく運びとなりました。

ずばり、
2017年は「Flexbox」です!

異論は受け付けておりませんので、何卒ご了承の程よろしくお願い申し上げます。

Flexboxとは何や

CSS3 Flexible Box – W3Schools
こちらをご覧いただければお分かりになる通り、一言で申し上げるとflexibleなboxということですね。
あまりごちゃごちゃと基本的なことを説明するよりも、手っ取り早く実際のWebサイトを例として実例をいくつかご紹介させていただきます。
※以下、実際のHTML,CSSから一部を編集・抜粋して引用させていただいております。

実例

最も簡単な横並びメニュー

Yahoo! JAPAN

ご存知、天下のYahoo! JAPANさんですね。
検索窓上部の横並びメニューを見てみましょう。

どんな具合になっているかというと、

<ul>
  <li><a href="#">メニュー</a></li>
  <li><a href="#">メニュー</a></li>
  <li><a href="#">メニュー</a></li>
</ul>
li {
  display: inline;
  padding: 0 5px;
}

このように、liをシンプルにdisplay: inline、つまり普通のテキストと同じように並ばせ、paddingでメニュー間の余白を調整するシンプルな作りになっています。

最もシンプルに横並びレイアウトを実現したい場合にはこれくらいシンプルでもまったく問題ありません。
例えばカテゴリー一覧やタグ一覧をシンプルに表示させたい場合にはまだまだ使える基本オブ基本のテクニックですね。
:hovertext-decoration: underlineなどしてあげてリンクされた要素であることを分かりやすくしてあげるとGOODです。

等幅×日本語+英語横並びメニュー

世界トップクラスのシェアを誇るレースタイム計測システム|Bee dancing

次は、コーポレートサイトなどでよく見かける「等幅×日本語+英語横並びメニュー」です。

こちらはどんな具合になっているかというと、

<ul>
  <li><a href="#"><span><b>メニュー1</b><small>MENU 1</small></span></a></li>
  <li><a href="#"><span><b>メニュー2</b><small>MENU 2</small></span></a></li>
  <li><a href="#"><span><b>メニュー3</b><small>MENU 3</small></span></a></li>
</ul>
li {
  display: inline-block;
  vertical-align: middle;
  width: 16.6%;
}

li > a {
  text-align: center;
  display: table;
  width: 100%;
  padding: 10px;
}

li > a span {
  display: table-cell;
  vertical-align: middle;
}

最も基本的な横並びレイアウトに比べるとすこし複雑になってはいますが、分解して見てみましょう。

まず、等幅でメニューを並べる部分はliに対してwidth: 16.6%(100% / 6 ≒ 16.6%)を指定しています。
※モダンブラウザではほとんどcalc()をサポートしているため、width: calc(100% / 6)でももちろんOKです!

そして、各メニューについては親であるadisplay: tableを、子であるspandisplay: table-cellをそれぞれ指定することで垂直方向のセンタリング(vertical-align: middle)を可能にしているわけです。

左寄せロゴ+右寄せメニュー

THE KEY HIGHLAND IZU [ザ キー ハイランド イズ]

こちらで採用されているヘッダーをFlexboxで実現してみます。

まずは、現状では

<header>
  <p>
    <a href="/">ロゴ</a>
  </p>
  <nav>
    <ul>
      <li><a href="#">メニューA</a></li>
      <li><a href="#">メニューB</a></li>
      <li><a href="#">メニューC</a></li>
    </ul>
  </nav>
</header>
header {
    text-align: right;
}

p a {
    position: absolute;
    left: 20px;
    top: 20px;
}

nav ul li {
    display: inline-block;
    margin-right: 25px;
}

このように、header内は右寄せにしつつ、ロゴのみposition: absoluteで固定、横並びメニューはinline-blockで実現、という形です。
では、これをFlexboxで実現してみます。

<header>
  <nav>
    <ul>
      <li><a href="/">ロゴ</a></li>
      <li><a href="#">メニューA</a></li>
      <li><a href="#">メニューB</a></li>
      <li><a href="#">メニューC</a></li>
    </ul>
  </nav>
</header>
ul {
  display: flex;

  li:first-child {
    margin-right: auto;
  }
}

以上です。
本当にありがとうございました。
ありがとうCSS3、ありがとうFlexbox

原理的には、ulの中にliを配置していくんですが、ulの中で領域が余ってしまうので、li:first-childmargin-rightが自動で空いた領域を埋めてくれる、という考え方でOKです。

左寄せ+中央+右寄せメニュー

KDS 熊本ドライビングスクール

こちらで採用されているメニューをFlexboxで実現してみます。

まずは、現状では

<ul>
  <a href="#"><li>メニューA</li></a>
  <a href="#"><li class="blue_bnr">メニューB</li></a>
  <a href="#"><li>メニューC</li></a>
  <br class="cl">
</ul>
li {
  float: left;
}

.blue_bnr {
  margin: 0 14px;
}

.cl {
  clear: both;
}

このように、各メニューをfloat: leftし、中央の要素で左右マージンを取るという形です。かつ、floatしたので、事後はしっかり解除しないといけません。
各要素が等間隔というだけであればすべての要素で左右マージンを取ればいいのですが、このケースではメニューA、メニューCがそれぞれ左寄せ、右寄せとなっているため、このような対応となっています。

では、これをFlexboxで実現してみます。

<ul>
	<a href="#"><li>メニューA</li></a>
	<a href="#"><li>メニューB</li></a>
	<a href="#"><li>メニューC</li></a>
</ul>
ul {
  display: flex;
  justify-content: space-between;
}

以上です。
本当にありがとうございました。
ありがとうCSS3、ありがとうFlexbox

justify-content: space-betweenをコンテナ(この場合ul)に当てることで、要素間のスペースが空いた領域を等幅で埋めてくれる、という考え方です。
アイテム(この場合li)にjustify-contentを当ててしまうと何回リロードしても思い通りになってくれないので、注意が必要です!

上下左右中央揃え

maio

こちらで採用されている上下左右中央揃えをFlexboxで実現してみます。

まずは、現状では

<div>
	<div class="inner">
		<h1>ロゴ</h1>
	</div>
</div>
div {
  position: relative;

  .inner {
    position: absolute;
    top: 52%;
    left: 50%;
    transform: translate(-50%,-50%);
  }
}

このように、親要素を基準に中央配置したい要素をposition: absolutetransform: translate()でうまいこと移動させています。

では、これをFlexboxで実現してみます。

<div>
	<div class="inner">
		<h1>ロゴ</h1>
	</div>
</div>
div {
  display: flex;
  align-items: center;
  justify-content: center;
}

こんな具合に、目的の要素の大小等に関わらずこれだけですべて事足りてしまうのです!

まとめ

ここまで、実際のWebサイトを例に挙げて参りましたが、いかがでしょうか?
少ないサンプルでもFlexboxの魅力はお分かりいただけたことと思います。
今回挙げた例以外にも、高さが不確定の複数要素を同じ高さにできたり、コンテナいっぱいにアイテムを広げたり、ここでは紹介できないほど有能な子なんです!!!

要はfloatinline-blocktable-cellも要らないんです!!!!!

clearfix忘れてレイアウト崩れ放題になることも、改行入れたせいで微妙にスペース空くことも、paddingは効くくせにmarginはうまく効かないこともないんです!!!

2017年、今年こそFlexbox元年とします!!!!!!

それでは、アデュー