display:flexで要素を横並びにする6種類の方法と注意点

HTMLの要素を横並びにしたくて、floatプロパティで四苦八苦していたのは昔の話し。今は display:flex で簡単にできるようになりました。

しかし、display:flex には特有のクセのようなものがあり、仕様をきちんと理解しないと、意図したとおりの横並びにできない場合があります。

今回は display:flex で横並びにする6種類の方法と、その注意点について解説していきます。

1. 普通の横並び

…
<style>
ul {
  display: flex;
    column-gap: 1em;
  list-style: none;
  padding: 0;
}
</style>
…
<ul>
  <li>List Item 1</li>
  …
  <li>List Item 4</li>
</ul>
…

display:flex を設定するだけで、その要素はフレックスコンテナ、その子要素はフレックスアイテムになり、横並びになります。

これは、フレックスアイテムの並ぶ方向を設定するflex-directionプロパティの初期値が「row (書字方向と平行の方向)」のためです。

フレックスアイテム間に余白を設定したい場合は、marginプロパティよりも、column-gapプロパティが便利です。

注意点

display:flex だけの場合、折り返しが行われないので、フレックスコンテナの幅やフレックスアイテムの数によっては、フレックスアイテムが潰れてしまいます。

これは、折り返しを設定するflex-wrapプロパティの初期値である「nowrap (折り返さない)」が適用されるためです。

フレックスアイテムを潰さずに折り返したい場合は、display:flex とともに flex-wrap:wrap を設定しましょう。

ul {
  display: flex;
    flex-wrap: wrap;
    column-gap: 1em;
  list-style: none;
  padding: 0;
}

2. 逆順で横並び

…
<style>
ul {
  display: flex;
    flex-direction: row-reverse;
    column-gap: 1em;
  list-style: none;
  padding: 0;
}
</style>
…
<ul>
  <li>List Item 1</li>
  …
  <li>List Item 4</li>
</ul>
…

flex-directionプロパティの値を、初期値の「row」から「row-reverse」に変更するだけで、フレックスアイテムを逆順に並び替えることができます。

注意点

flex-direction:row-reverse で逆順にすると配置も逆転します。具体的には、書字方向が左から右の場合、flex-direction:row は左揃えになりますが、flex-direction:row-reverse は右揃えになります。

flex-direction:row-reverse でも flex-direction:row と同じ揃え方にしたい場合は、justify-content:flex-end を設定します。

ul {
  display: flex;
    flex-direction: row-reverse;
    column-gap: 1em;
    justify-content: flex-end;
  list-style: none;
  padding: 0;
}

3. 均等幅で横並び その1

…
<style>
ul {
  display: flex;
  list-style: none;
  padding: 0;
}
li {
  flex-basis: 100%;
}
</style>
…
<ul>
  <li>List Item 1</li>
  …
  <li>List Item 4</li>
</ul>
…

均等幅で横並びにするには、フレックスアイテムに flex-basis:100% を設定します。100%で均等幅になる理由は、flex-shrinkプロパティの初期値である「1」が適用されるためです。

flex-shrinkプロパティは、フレックスアイテムがフレックスコンテナからはみ出してしまう状況になった際、はみ出してしまう幅を、フレックスアイテムに分配する比率 (縮み率) を設定します。

例えば、フレックスコンテナの幅が240pxで、flex-basis:100% のフレックスアイテムが4つあった場合、はみ出してしまう幅は720px (= 240px * 4 – 240px) になります。すべてのフレックスアイテムに flex-shrink:1 が設定してあると、この720pxを 1:1:1:1 の比率で分配するので、各フレックスアイテムが180px (= 720px / 4) 縮み、結果的に60px (= 240px – 180px) の均等幅となります。

注意点

この方法は、flex-wrapプロパティの値が「nowrap (折り返さない)」である場合にのみ有効です。flex-wrap:wrap にした場合、フレックスアイテムが縦に並んでしまいます。

4. 均等幅で横並び その2

…
<style>
ul {
  display: flex;
    flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li {
  flex-grow: 1;
  flex-basis: 120px;
}
</style>
…
<ul>
  <li>List Item 1</li>
  …
  <li>List Item 4</li>
</ul>
…

flex-wrap:wrap で折り返されるようにしつつ、均等幅で横並びにするには、flex-basisプロパティで最小幅を設定し、flex-grow:1 を設定します。

flex-growプロパティは、フレックスアイテムを並べた際にできた空白部分の幅を、フレックスアイテムに分配する比率 (伸び率) を設定します。

例えば、フレックスコンテナの幅が720pxで、flex-basis:120px のフレックスアイテムが4つあった場合、空白部分の幅は240px (= 720px – 120px * 4) になります。すべてのフレックスアイテムに flex-grow:1 が設定してあると、この240pxを 1:1:1:1 の比率で分配するので、各フレックスアイテムが60px (= 240px / 4) 伸び、結果的に180px (= 120px + 60px) の均等幅となります。

注意点

折り返しによってできた最後の段には、大きな空白部分ができやすく、flex-growプロパティによって幅が分配されるため、最後の段だけ分割数が異なる均等幅になってしまいます。

5. 均等幅で横並び その3

…
<style>
ul {
  display: flex;
    flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li {
  flex-basis: 120px;
}
</style>
…
<ul>
  <li>List Item 1</li>
  …
  <li>List Item 6</li>
</ul>
…

折り返されたフレックスアイテムの幅も統一したい場合は、flex-growプロパティは初期値の「0」のまま、flex-basisプロパティで任意の幅を設定し、すべてのフレックスアイテムの幅を統一します。

幅を%値で設定すれば、最後の段以外、フレックスコンテナの端から端まで埋めることができます。

li {
  flex-basis: calc(100% / 4);
}

注意点

フレックスアイテムを任意の幅で固定するので、フレックスコンテナの幅やフレックスアイテムの数によって空白部分が生じます。

6. 空白部分を均等幅にした横並び

…
<style>
ul {
  display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  list-style: none;
  padding: 0;
}
</style>
…
<ul>
  <li>List Item 1</li>
  …
  <li>List Item 10</li>
</ul>
…

justify-contentプロパティに「space-」から始まる値を設定します。「space-」から始まる値は現在、「space-between」「space-around」「space-evenly」の3種類があります。

space-between
フレックスアイテム間の空白部分の幅を均等にします。
space-around
フレックスアイテム前後の空白部分の幅を均等にします。
space-evenly
フレックスアイテム間と各段の最初と最後の空白部分の幅を均等にします。

注意点

各段毎に空白部分が均等幅に揃えられるため、複数段になる場合、各段で空白部分の幅が異なってしまいます。

まとめ

横並びにする6種類の方法を紹介しましたが、その注意点は、折り返さなければフレックスアイテムが潰れてしまい、折り返せばフレックスアイテムや空白部分の幅に問題が出るといった、flex-wrapプロパティとflex-growプロパティの設定に起因していると思います。

これらの問題が発生しないようにするには、flex-growプロパティを使用する際には、折り返すことを前提としないか、折り返しが必要になる状況では横並びを解除するといいでしょう。その場合、次のようなコードが良さそうです。

ul {
  display: flex;
    flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li {
  flex-grow: 1;
  flex-basis: clamp(120px, (481px - 100%) * 480, 100%);
}

このコードのflex-basisプロパティには、フレックスアイテムの数は最大で4つ、その最小幅が120pxになることを前提としたclamp関数値が設定してあります。

これにより、フレックスコンテナの幅が481px以上ならフレックスアイテムは4等分の横並びに、480px以下なら縦並びになります。

display:flexを使うことで簡単にレイアウトを組むことができますが、意外と思い描いたレイアウトが実現できなかったりするんですよね。

関連記事