よこ並びのCSS。
フロートでよこ並び

そのむかし、よこ並びCSSといえばfloatプロパティでした。よこ並びといえば、ほぼfloatプロパティだけでまかなっていましたよね。現在はよこ並びとして使うのは危ぶまれがちなfloatプロパティですが、フレキシブルレイアウトやグリッドレイアウトとは違う、特殊なよこ並びの手法のひとつとして、覚えておいても良いんじゃないかなと思います。

フロートでのレイアウト

ご存知、floatプロパティは本来、よこ並びするためのプロパティではなく、特定の要素を左右に寄せて配置するためのプロパティです。
例えば、下のサンプルみたく、文章中の挿絵をレイアウトする時。img要素に対してfloat: leftと指定すれば、画像は左側に寄り、float: rightと指定すれば、画像は右側に寄り、その後に続く要素は、画像を避けながら、その隣に回り込むようにレイアウトされます。

フロートでのよこ並び

そんなfloatプロパティを使って要素をよこ並びにしてみます。
例えば下のサンプルのようなナビゲーションならば、li要素すべてにfloat: leftを指定して、続々と左へ寄せることで、横一列に並べることができます。横幅を指定しなければ、その要素の内容(ここでは文字数)に準拠した横幅でよこ並びになります。
また、ふたつめ以降のli要素li:nth-child(n+2)の左側に1pxのパディングを指定して、ボタンごとに隙間を空けています。

li {
	float: left;
}
li:nth-child(n+2) {
	padding-left: 1px;
}

※フロートした後には、フロート解除も忘れずに。ここでは、.cfというクラスでclearfixを適用しています。

.cf::after {
	content: "";
	display: block;
	clear: both;
}

clearfixについては下記記事が詳しいです。
floatを解除する手法のclearfix と 次世代のレイアウトの話|Web Design KOJIKA17(2013.6.30)

ページトップへ戻る

ナビゲーションを中央に配置する

上のサンプルだと、ナビゲーション全体が左に寄っちゃってますけれど、中央に配置したいなって時には、ナビゲーションのさらに親の要素にtext-align: centerを指定して、ナビゲーション自体にはdisplayプロパティでinline-blockと指定することで、中央に配置されます。inline-blockを指定することで、要素の大きさがその要素の内容(ここではナビゲーションの幅)に準拠した大きさになり、テキストと同じように扱われるんです。
ここではul要素をnav要素で括って、nav要素にtext-align: center、ul要素にdisplay: inline-blockを指定してます。

nav {
	text-align: center;
	background: #fafafa;
}
ul {
	list-style: none;
	display: inline-block;
	margin: 0;
	padding: 0;
}

よく見ると、ナビゲーションの下に妙な余白があるのがわかりますね…。inline-blockを指定したことで、ul要素の縦方向の位置が、ベースラインに揃うようになったのが原因。

inline-blockな要素は、テキストと同じように扱われる

ベースラインに揃うのは、vertical-alignプロパティの初期値、baselineの影響なので、ここではvertical-align: middleと指定することで、余白が出ないようにしています。

ul {
	list-style: none;
	display: inline-block;
	margin: 0;
	padding: 0;
	vertical-align: middle;
}

親要素で括りたくない時

どうしても親要素で括りたくない、親要素で括るのが憚られる、という場合には下のサンプルのようにして、中央に配置することができます。

ul要素に、position: relativeと指定することで、leftプロパティで要素の位置を動かせるようになります。left: 50%という指定で、ul要素の左辺が画面の中央(左端から50%の位置)にくるように配置されます。さらに、transformプロパティのtranslateX()という関数を使って、ul要素の横幅の50%分、左方向へ移動しています。
ただしこのままだと、ul要素の横幅が画面の横幅と同じなので、結局元の位置に戻ることになっちゃいます…。そこで、ul要素にdisplay: inline-blockを指定します。これで、ul要素の横幅が内容に準拠した大きさになり、うまく中央に配置されるってわけです;)
前述の方法にもあった通り、inline-blockを指定すると、下に妙な隙間ができてしまうので、vertical-align: middleも指定しておきます。

ul {
	list-style: none;
	display: inline-block;
	position: relative;
	left: 50%;
	margin: 0;
	padding: 0;
	vertical-align: middle;
	transform: translateX(-50%);
}
translateX()でのパーセント指定は、その要素の横幅が基準となる

ページトップへ戻る

ナビゲーションを横幅いっぱいにレイアウトする

ナビゲーション全体を親要素の横幅いっぱいに広げたい場合には、widthプロパティの値の合計が100%となるように、li要素の横幅を20%に指定します。

li {
	float: left;
	width: 20%;
}

ありゃ、なんだか変なふうになっちゃいました。最後のボタンが改行しちゃってます…:(。paddingプロパティを指定した要素にwidth/heightプロパティでサイズを指定した場合、paddingの値は指定した横幅の外に適用されるんですね、困った…。
こんな時は、box-sizingプロパティborder-boxを指定しておきます。すると、width/heightプロパティで指定したサイズに、padding/borderプロパティの値も含めて適用されるようになるので、計算しやすくなって便利:)
ついでにボタンの中のテキストもボタンの中央に配置されるように調整しておきます。

li {
	float: left;
	width: 20%;
	box-sizing: border-box;
	text-align: center;
}

ただ、文字数によって改行されると、ボタンの大きさが揃わなくてかっこ悪いです。
下のサンプルみたく、なるべく1行になるように、文字数に合わせてボタンの横幅を調整するのは、面倒臭いからちょっとヤかも…。

li {
	float: left;
	width: 17%;
	box-sizing: border-box;
	text-align: center;
}
li:nth-child(2) {
	width: 36%;
}
li:nth-child(3),
li:nth-child(5) {
	width: 15%;
}

そんな時にはテーブルレイアウトを使う方法が便利ですけれど、それはまた別のお話。

テーブルレイアウトでよこ並び

ページトップへ戻る

フロートで商品一覧

3分割なので、li要素の横幅を、全体の33.333333%と指定して、それぞれにfloat: leftを指定します。

.itemlist li {
	float: left;
	width: 33.333333%;
	padding: 10px;
	box-sizing: border-box;
}

2段になるはずが、4つめの商品が真ん中に配置されちゃって、グチャグチャになっちゃいました…X(。フロートした要素の後に続く要素は、フロートした要素の隣へ隣へと並びたがるので、ちょっとでも隣に並べそうな隙間があるとそこへ並んじゃうんです…。最初の商品が、あとの2つの商品よりも文量が多くて縦に長い分、4つめの商品が、その隣に並んでしまってます。

これを正すために、clearプロパティを使います。clearプロパティを指定した要素は、先行する要素の隣に並ぼうとしなくなるんです。たとえば、clear: leftと指定した要素は、先行する要素が左へフロートしていても、それに流されることなく下へ配置されるということ。
3列に並んでるので、改行しなきゃならん要素は、“3つめの次”。これを:nth-child擬似クラスを使って下図のように表します。

.itemlist li:nth-child(3n+1) {
	clear: left;
}

綺麗に並びました。けど、スマホで見ている人は気づいてしまっているかもしれませんが、横幅が狭い時に、商品がすっごい小さくなってしまってます。横幅が狭くなったら横の列数を少なくなるようにしたいです、そう、レスポンシブに!:)

レスポンシブにする

レスポンシブ(Responsive)とは、“反応する”という意味があって、レスポンシブWebデザインというと、Webサイトを閲覧している環境や、画面サイズに応じて、適したデザインで閲覧できるように調整されたWebデザインのことを言います。
このサンプルみたいなレイアウトの商品一覧の場合には、横幅に合わせて並べる列数を切り替えて調整することが多いです。

レスポンシブに表示を切り替えるにはメディアクエリを利用します。@mediaルールという構文を使って、スタイルが適用される時の画面の横幅を制限することで、画面幅に合わせて、レイアウトを切り替えることができるようになります。
ここでは、767px以下の時は2列、414px以下の時には1列になるようにします。

※767px以下とはつまりiPad未満(iPadを含まない、それよりも小さい画面サイズ)ということ。※414pxはちょうどiPhone6 Plusの画面の横幅サイズになります。

@media screen and (max-width: 767px) {
	.itemlist li {
		width: 50%;
	}
}
@media screen and (max-width: 414px) {
	.itemlist li {
		width: 100%;
	}
}

2列の時にまたグチャッちゃいました…。2列ずつになって改行位置が変わったので、clearする要素を変えねばなりません。今度は、“2つめの次”にclearプロパティを適用します。“3つめの次”に指定してたclearプロパティは、noneと指定しておきます。
414px以下の時には、“2つめの次”のclearプロパティもnoneと指定しておきましょう。
フロートで商品一覧は一丁あがり!

@media screen and (max-width: 767px) {
	.itemlist li {
		width: 50%;
	}
	.itemlist li:nth-child(3n+1) {
		clear: none;
	}
	.itemlist li:nth-child(2n+1) {
		clear: left;
	}
}
@media screen and (max-width: 414px) {
	.itemlist li {
		float: none;
		width: 100%;
	}
	.itemlist li:nth-child(2n+1) {
		clear: none;
	}
}

メディアクエリについて、詳しくは下記ページを参照のこと。
メディアクエリの利用 - CSS: カスケーディングスタイルシート | MDN

ページトップへ戻る

効率的な指定方法

とはいえ、上の指定方法だと、clearプロパティの値を上書きに上書きを重ねてるあたり、ちょっと非効率な気がしますね:(。本当に指定が必要なところだけ指定できれば、もっと効率的になるはず!
まずフロートするのは415px以上の時だけです。それから、3分割するのは768px以上の時だけだし、2分割するのは767px〜415pxの間だけですね。それらを鑑みてメディアクエリを指定すると、以下のようになりました。

.itemlist li {
	padding: 10px;
	box-sizing: border-box;
}
@media screen and (min-width: 415px) {
	.itemlist li {
		float: left;
	}
}
@media screen and (min-width: 768px) {
	.itemlist li {
		width: 33.333333%;
	}
	.itemlist li:nth-child(3n+1) {
		clear: left;
	}
}
@media screen and (max-width: 767px) and (min-width: 415px) {
	.itemlist li {
		width: 50%;
	}
	.itemlist li:nth-child(2n+1) {
		clear: left;
	}
}

※さっきは「〜以下の時は」という指定の仕方だったので、「767px以下414px以下」の順(幅が広い方から狭い方の順)に指定してました。けれども今度は「〜以上の時は」という指定の仕方になってるので、「415px以上768px以上」の順(幅が狭い方から広い方の順)に指定してる点に注意です:o

※先述の書き方だと、(min-width: 415px)(min-width: 768px)の、.itemlist liの指定が冗長なので、上のサンプルではそこは(min-width: 415px)の中にまとめて書いて、(max-width: 767px) and (min-width: 415px)で上書きするようにしています:)

Comment & Pingback

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください