flexboxの使い方!CSSレイアウトの基本を徹底解説

CSS Flexboxで要素を横並び・縦並びにレイアウトする方法のイメージ図

この記事の前提条件

対象: CSS(全モダンブラウザ対応)
難易度: ★☆☆
所要時間: 約10分

「横並びにしたいのに崩れる」「縦横中央に揃えたいだけなのに、なぜかCSSが複雑になる」…レイアウト組みでそんな沼にハマった経験、ありませんか?flexbox(フレックスボックス)を使えば、そのほとんどが数行のCSSで解決します。floatやposition:absoluteを駆使していた頃と比べると、驚くほどシンプルです。

flexboxの基本: 親要素にdisplay:flexを指定する

flexboxは「親要素」と「子要素」のセットで動く仕組みです。まず、並べたい要素をまとめている親要素にdisplay: flex;を指定します。これだけで、中の子要素が自動的に横並びになります。

<div class="flex-container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
.flex-container {
  display: flex;
}

本来、div要素は縦に積み重なっていくブロック要素ですが、親にdisplay: flex;を指定するだけで、子要素が横一列に並びます。floatのように「回り込み解除(clearfix)」を別途書く必要もありません。

要素の間隔を揃える: justify-content

横並びにした要素を「均等に広げたい」「右寄せにしたい」といった配置調整は、親要素にjustify-contentを指定するだけで完結します。

.flex-container {
  display: flex;
  justify-content: space-between; /* 両端揃え、間隔は均等 */
}

他にもよく使う値には、中央に寄せるcenter、右寄せにするflex-endなどがあります。まずはspace-betweenを基準に、配置を変えたい時に値だけ書き換えてみてください。

ナビゲーションメニューを均等配置したい時や、カードを並べる時など、実務で一番出番が多いプロパティです。

縦横中央揃えを1行で: align-items

「要素を縦横中央に揃える」は、CSSの中でも特につまずきやすいポイントとして有名ですが、flexboxならjustify-content: center;align-items: center;の2行だけで完結します。

.flex-container {
  display: flex;
  justify-content: center; /* 横方向の中央揃え */
  align-items: center;     /* 縦方向の中央揃え */
  height: 300px;
}
💡 「position:absoluteで中央揃え」との使い分け

1つの要素だけをピンポイントで中央に固定したい場合(位置が動かない前提)はposition: absolute;で組む方がシンプルなこともあります。一方、複数の要素を並べつつ中央揃えにしたい場合や、要素数が可変する場合は、flexboxの方が圧倒的に管理しやすいです。用途に応じて使い分けましょう。

画面幅が足りない時に折り返す: flex-wrap

flexboxは初期状態だと、子要素の合計幅が親要素より大きくなっても折り返さず、無理やり縮めてでも1行に収めようとします。幅を固定したカードを並べる一覧などでは、この挙動のせいで要素が想定より潰れて見えることがあります。

.flex-container {
  display: flex;
  flex-wrap: wrap; /* 収まらない分は次の行に折り返す */
}

flex-wrap: wrap;を指定すると、収まりきらない要素は自動的に次の行へ折り返されます。カード一覧やタグ一覧のように「入るだけ並べて、余ったら次の行へ」というレイアウトでは、ほぼ必須のプロパティです。

要素同士の余白をまとめて指定する: gap

以前は要素の間隔を空けるために、margin-rightを指定してから最後の要素だけ:last-childで打ち消す、といった面倒な書き方が定番でした。今はgapプロパティを親要素に指定するだけで、要素間の余白をまとめて管理できます。

.flex-container {
  display: flex;
  gap: 20px; /* 縦横まとめて指定 */
}

行間だけ・列の間隔だけを別々に指定したい場合は、row-gapcolumn-gapにそれぞれ分けて書くこともできます。

💡 gapは主要ブラウザで問題なく使える

以前はflexboxでのgap対応がSafariで遅れていましたが、2021年以降のバージョンで対応済みです。今から新しく書くコードであれば、marginでの間隔調整よりgapを優先して問題ありません。

子要素の伸び縮みを配分する: flexショートハンド

flexboxの中でも一番つまずきやすく、同時に一番重要なのが「伸び縮みの配分」です。子要素にはデフォルトで「必要なら縮んででも並びを維持しようとする」性質(flex-shrink: 1)があり、長いテキストや画像が入ると意図せず幅が潰れることがあります。

これを制御するのが次の3つのプロパティで、実務ではflexというショートハンドでまとめて書くのが一般的です。

  • flex-grow: 余った幅をどう配分するか(数字が大きいほど多く広がる)
  • flex-shrink: 幅が足りない時にどう縮めるか(0にすると縮まなくなる)
  • flex-basis: 伸び縮みする前の基準サイズ
/* 3カラムを常に均等幅にする(一番よく使うパターン) */
.item {
  flex: 1; /* flex-grow:1 flex-shrink:1 flex-basis:0% の省略形 */
}

/* サイズを変えたくない要素(アイコンなど)には */
.icon {
  flex: 0 0 40px; /* 伸びも縮みもせず、常に40px */
}

画像やアイコンなど「絶対にサイズを変えたくない」要素だけflex-shrink: 0;を個別に指定する方法もありますが、レイアウト全体の意図が伝わりやすいという点で、実務ではflexショートハンドで書く方をおすすめします。

HTMLの順番を変えずに表示順を入れ替える: order

「スマホでは画像を先に表示したいけど、HTMLの構造(文章としての意味の順番)は変えたくない」——そんな場面で使えるのがorderです。数字が小さいほど先に表示され、初期値は全要素0のため、負の数を指定すると先頭に持ってこられます。

.image { order: -1; } /* HTML上は後ろでも、表示は先頭になる */
⚠️ 見た目の順番と読み上げ順がズレることに注意

スクリーンリーダーやキーボード操作でのタブ移動は、CSSのorderではなくHTMLの記述順に従います。見た目の順番だけを変えるつもりが、視覚的な順序と操作上の順序が食い違って混乱を招くことがあるため、乖離を大きくしすぎないよう注意しましょう。

複数行になった時の行間隔を揃える: align-content

align-itemsが「1行の中での縦位置」を揃えるのに対し、align-contentflex-wrap: wrap;で複数行になった時の「行と行の間隔・全体の縦位置」を揃えるプロパティです。名前が似ていて混同しやすいですが、役割は別物です。

.flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between; /* 複数行全体を上下に均等配置 */
}

flex-wrap: wrap;を指定していない(=1行しかない)場合、align-contentは何も効果を持ちません。「指定したのに効かない」と感じたら、まずflex-wrapの指定を確認してみてください。

特定の要素だけ配置を変える: align-self

align-itemsは親要素に指定して全ての子要素に一括で効きますが、「1つの要素だけ縦位置を変えたい」場合は、その要素自身にalign-selfを指定します。

.flex-container {
  display: flex;
  align-items: center; /* 基本は全部センター揃え */
}
.item-only-this {
  align-self: flex-end; /* この要素だけ下揃えにする */
}

スマホでは縦並びにしたい場合: flex-direction

PCでは横並び、スマホでは縦並びにしたいケースも多いはずです。メディアクエリと組み合わせて、flex-direction: column;を指定すれば並び方向を縦に切り替えられます。

@media (max-width: 768px) {
  .flex-container {
    flex-direction: column;
  }
}

まとめ

  • 親要素にdisplay: flex;を指定するだけで子要素が横並びになる
  • 横方向の配置はjustify-content、縦方向の配置はalign-itemsで調整する
  • 収まらない要素を折り返すにはflex-wrap: wrap;、間隔はgapでまとめて指定できる
  • 子要素の伸び縮みはflexショートハンド(flex-grow/flex-shrink/flex-basis)で配分する
  • 表示順序だけ変えたい時はorder、複数行の縦間隔はalign-content、特定の要素だけの配置はalign-self
  • スマホではflex-direction: column;で縦並びに切り替えられる

floatを使った古いレイアウト手法に比べると、flexboxは圧倒的に直感的です。まずは横並びと中央揃えの2つから使ってみて、慣れてきたらflexショートハンドやgapも使いこなせるようになると、実務での再現度がぐっと上がります。行と列の両方を同時にコントロールしたい、より複雑な2次元のレイアウトを組みたい場合は、CSS Gridも合わせて覚えておくと選択肢が広がります。