すたらブログ

文系Webプログラマの備忘録

CSS: ブロック要素を折り返しつつ横並びで表示させる方法

(最終更新: 2016-11-03)

目次

写真のサムネイルなど、数量不定で大量の要素を横並びに表示させ、画面幅に収まらない場合は次の行に折り返す方法について考えます。


高さを揃えれば崩れない

要素の高さが全て同じならば、floatで手軽に実現できます。
画面幅に応じて、1行内の要素数は柔軟に変わります。
まあ、単にカラム落ちしているだけですが。

<div class="container">
  <div class="item blue"></div>
  <div class="item purple"></div>
  <div class="item blue"></div>
.item {
  float: left;
}

高さがバラバラだと崩れる

floatの問題点として、要素の高さが極端に異なると改行がうまくいかない場合があります。
上の写真では2行目が正しく改行されていません。


1行内の要素数を固定すれば崩れない

1行内の要素数を固定し、割合に応じたwidthmax-widthを設定し、画面幅が極端に狭ければフロートさせない、などの設定をすれば表示は崩れません。
しかし、柔軟な折り返しはできないし管理しづらいです。

<div class="container">
  <div class="item purple"></div>
  <div class="item blue"></div>
  <div class="item purple"></div>
  <div class="item blue"></div>
  <div class="item purple"></div>
</div><!-- 予め決めておいた1行内の数に応じて親要素を閉じる -->
<div class="container">
  <div class="item blue"></div>
</div>
.item {
  float: left;
  max-width: 102px;
  width: 20%;
}
@media screen and (max-width: 320px) {
  .item {
    float: none;
    width: auto;
  }
}

flexboxで完全解決

CSS3のフレックス・ボックスを使えば、高さを気にせずシンプルなHTML構造で柔軟に表示できます。
ただし、対応ブラウザはIE10以上です。

.container {
  /* この要素はflexコンテナとなり、子要素は自動的にflexアイテムとなる */
  display: flex;

  /* 横並びに表示する */
  flex-direction: row;

  /* 画面幅に収まらない場合は折り返す */
  flex-wrap: wrap;
}

JavaScriptでも解決できる

何もしなければ、当然配置が崩れます。

JavaScriptで高さを揃えれば崩れません。
flexboxが使えないIE9で、高さが統一されていない要素を柔軟に並べるには、この方法しかないと思います。

下記のように各要素の高さを全て配列に格納して、その最大値で高さを統一しています。
詳しくはソースコードをご覧ください。

var arr_height = [];
$('.container2 .item').each(function() {
  arr_height.push($(this).height());
});
$('.container2 .item').height(Math.max.apply(null, arr_height));
});

まとめ

まだまだIE8、IE9に対応しなければならないことが多いので、フレックス・ボックスは使えません。
そうなると、下記の二者択一となります。

  1. 柔軟な折り返しのため、要素の高さを固定する。
  2. 要素の高さの自由を得るため、柔軟な折り返しを諦めて1行内の要素数を固定する。

または、JavaScriptで解決することもできます。