【HTML/CSS】CSS横並び指定はflexで!calc関数とnth-childで余白調整が便利!
要素を等間隔で横並びにすることってWEBコーディングで絶対に出てきますよね。
横並びの方法はfloat・inline-block・tableなど色々ありますが、レスポンシブ対応も必須な今はとにかくdisplay:flexが便利です。
幅以上に要素があってもwrap指定で簡単に折り返してくれるし、
更にcalc関数を使って余白を計算してパーセント指定すると、横幅を変動してもレイアウト崩れが起きません。
またnth-childで改行手前の要素の余白を消す処理をすれば、横並びが繰り返されても崩れません。
それに要素内の水平・垂直方向中央もカンタン!
長い間floatで苦労してきたけど、素敵な時代が来たなあ・・と思うこの頃です。
CSS横並び指定はflexで!calc関数とnth-childで余白調整が便利!
display:flexで横並び指定
デモサイト作成しましたので、まずはご覧ください。
写真とテキストが入ったアイテムが横に3列並んでいる下記の状態をdisplay:flexでコーディングしてみます。
要素が6つ、PCで横並び3列、スマホで横並び2列になるように指定してみます。
まずは要素6つをdivで囲います。
HTML
<div class="items"> <!-- item --> <div class="item"> <img src="img/sea01.jpg" alt="海岸"> <p>これはテストです</p> </div> <!-- item --> <!-- item --> <div class="item"> <img src="img/sea01.jpg" alt="海岸"> <p>これはテストです</p> </div> <!-- item --> <!-- item --> <div class="item"> <img src="img/sea01.jpg" alt="海岸"> <p>これはテストです</p> </div> <!-- item --> <!-- item --> <div class="item"> <img src="img/sea01.jpg" alt="海岸"> <p>これはテストです</p> </div> <!-- item --> <!-- item --> <div class="item"> <img src="img/sea01.jpg" alt="海岸"> <p>これはテストです</p> </div> <!-- item --> <!-- item --> <div class="item"> <img src="img/sea01.jpg" alt="海岸"> <p>これはテストです</p> </div> <!-- item --> </div>
item要素には海の写真とテキストがあります。
このitem要素6つをitemsで囲みました。
このitemを横並びにするには、囲ったitemsにflex指定をします。
CSS
.items{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; } .item{ box-sizing: border-box; border:1px solid #ccc; margin: 0; padding: 20px; width: 33.33333333%; }
親要素itemsにflex指定、flex-wrapで子要素の折り返しを指定しています。
itemでは今の時点では内側の余白を指定して、PCで3列表示として33.33333333%とパーセント指定しました。
尚、flex-wrapにはほかに下記の指定が可能です。
・flex-wrap:wrap ・・・子要素を折り返し、複数行に上から下へ並べる
・flex-wrap:nowrap ・・・子要素を折り返さず一行に並べる
・flex-wrap:wrap-reverse・・・子要素を折り返し、複数行に下から上へ並べる
justify-contentは水平方向の揃えを指定できます。
・center … 中央揃え
・flex-start(初期値)… 行の開始位置から配置。左揃え。
・flex-end … 行末から配置。右揃え。
align-itemsは垂直方向の揃え揃えを指定できます。
・center … 中央揃え
・stretch(初期値)… 親要素の高さ、またはコンテンツの一番多い子要素の高さに合わせて広げて配置
・flex-start … 親要素の開始位置から配置。上揃え。
・flex-end … 親要素の終点から配置。下揃え。
外側余白marginを指定
item間の余白を50pxとります。右と下に50px余白を付けるので
margin:0 50px 50px 0と指定します。
CSS
.item{ margin:0 50px 50px 0; }
この状態だと、item横幅が33.333333%(横幅) + 50px (余白)となったため、
50pxがそれぞれ溢れてしまっているため、カラム落ちします。
calc関数で横幅指定
ここでcalc関数が登場します。
溢れないように33.333333%からmargin分の横幅を引きます。
calcはパーセントでも固定値でも計算できるので便利です。
CSS
.item{ margin:0 50px 50px 0; width:calc(33.3333333% - 50px); }
カラム落ちはなくなりました。
しかし、3つ目アイテムのmargin-right:50pxがあるため、右側に微妙に余白ができてしまいます。
1つ目、3つ目とも両端に配置して、ちょうどよく等配分するには、3つ目は右余白を0にする必要があります。
指定した個数目のアイテム余白を0に(nth-childで余白調整)
3つ目itemの余白を0にする指定を入れます。
nth-child()という擬似クラスで指定します。
3つ目、6つ目両方の右側余白を0にしたいので、3の倍数で指定する3nを使います。
CSS
.item:nth-child(3n){ margin-right:0; }
他の余白も調整
次にitemの幅を余白も考えた幅に調整します。
3つ並んだ場合、要素間の横の余白は50pxと50pxで合計100pxになります。
この100pxを3つのitemに均等に分けるには、下記のような計算を使うことができます。
css
.item{ margin:0 50px 50px 0; width:calc(33.3333333% - 100px / 3); }
100pxの3分の1の幅を3等分の横幅33.333333%から引くと、marginで50px取ってもカラム落ちせず、均等に並べることができます。
幅を縮めても、余白は50pxのままで他は均等にレスポンシブ化されます。
スマホでは2列に変えてみる。余白も狭く設定変更
スマホから見た場合には横2列に並べたい場合は、itemの幅と余白の計算、nth-child()の値が変わります。
表示するメディアの横幅が689px以下の場合2列に表示する場合は下記のコードを加えます。
また、余白を50pxから20pxに変更して要素内を少しでも大きく表示されるようにしてみます。
CSS
@media screen and (max-width:689px){ .item{ margin:0 20px 20px 0; width: calc(50% - 20px / 2); } .item:nth-child(2n){ margin-right:0; } .item:nth-child(3n){ margin-right:20px; } .item:nth-child(6){ margin-right:0; } }
689px幅以下の場合は2の倍数の右余白を0にしたいので、nth-child(2n)
と指定します。
同時にPCの場合に指定していた3の倍数の右余白0を、もとに戻して20pxと指定しなおします。
注意しなければならないのですが、2の倍数と3の倍数が重なる6つ目の要素には
後から指定した3nの20pxの余白が適用されてしまい、カラム落ちしてしまいます。
そのため、最後にnth-child(6)
と数字を入力して余白0を指定しています。
デモサイトはこちらです。
まとめ
横幅をcalc関数でパーセントを使って余白も計算して指定すると、どんな横幅に調整されても崩れません。
今回は折り返し要素を指定しましたが、折り返さず一列にまとめればグローバルメニューにも利用できます。
文字もalign-itemとjustify-contentで要素中央表示にできるので、設定が簡単ですよ。