- CSS
CSS flexboxの使い方早見表|横並び・中央寄せのコピペ集と効かない原因
CSS flexbox(フレックスボックス)とは、親要素に display: flex を指定するだけで、子要素を横や縦に並べ、位置・間隔・伸び縮みをまとめて指定できるレイアウトの仕組みです。 横並び、上下左右の中央寄せ、両端揃え、等幅カラムといった定番の配置が、数行のCSSで書けます。
この記事では、justify-contentとalign-itemsの全組み合わせを図にした早見表と、そのまま貼って使えるコピペ用コードをまとめました。間隔の指定はgapを標準にし、flex: 1 の伸縮がどう計算されるかを数値例で確かめ、「指定したのに効かない」ときの原因を再現コードと直し方で整理しています。数値はすべて Chromium 141(Playwright 1.56)で要素の位置とサイズを実測したものです。
flexboxの早見表
やりたいことから書き方を引ける表です。 すべて「親要素」に書くのが基本で、子要素に書くものは明記しています。
| やりたいこと | 書くCSS | 書く場所 |
|---|---|---|
| 横に並べる | display: flex; |
親 |
| 縦に並べる | display: flex; flex-direction: column; |
親 |
| 間隔をあける | gap: 16px; |
親 |
| 左右中央に寄せる | justify-content: center; |
親 |
| 上下中央に寄せる | align-items: center;(親に高さが必要) |
親 |
| 上下左右の中央に置く | justify-content: center; align-items: center; |
親 |
| 両端に揃える | justify-content: space-between; |
親 |
| 右に寄せる | justify-content: flex-end; |
親 |
| 1つだけ右に寄せる | margin-left: auto; |
子 |
| 折り返す | flex-wrap: wrap; |
親 |
| 等幅に並べる | flex: 1; |
子 |
| 幅を固定する | flex: 0 0 200px; |
子 |
| 残りの幅をすべて使う | flex: 1; min-width: 0; |
子 |
| フッターを下に固定する | 親に display: flex; flex-direction: column; min-height: 100vh;、本文に flex: 1; |
親と子 |
| 1つだけ上下の位置を変える | align-self: flex-end; |
子 |
| 並び順を変える | order: -1; |
子 |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS flexboxの使い方早見表|横並び・中央寄せのコピペ集と効かない原因」
flexboxの基本:親と子、主軸と交差軸
flexboxには2つの登場人物がいます。display: flex を指定した親要素(flexコンテナー)と、その直下の子要素(flexアイテム)です。孫要素はflexアイテムにはなりません。
<div class="row"> <!-- 親:flexコンテナー -->
<div>1</div> <!-- 子:flexアイテム -->
<div>2</div>
<div>3</div>
</div>
.row {
display: flex;
gap: 12px;
}
もう1つ押さえておきたいのが軸です。子要素が並ぶ方向を主軸、それと直角の方向を交差軸と呼びます。
| flex-directionの値 | 主軸(並ぶ方向) | 交差軸 | justify-contentが動かす方向 | align-itemsが動かす方向 |
|---|---|---|---|---|
row(初期値) |
左から右 | 上から下 | 左右 | 上下 |
row-reverse |
右から左 | 上から下 | 左右 | 上下 |
column |
上から下 | 左から右 | 上下 | 左右 |
column-reverse |
下から上 | 左から右 | 上下 | 左右 |
justify-contentは主軸、align-itemsは交差軸を担当します。flex-direction: column にすると2つの役割が入れ替わる点が、最初につまずきやすいところです。
プロパティ一覧(親に書くもの・子に書くもの)
| 書く場所 | プロパティ | 役割 | 初期値 |
|---|---|---|---|
| 親 | display |
flex(ブロックとして振る舞う)か inline-flex(インラインとして振る舞う) |
- |
| 親 | flex-direction |
並ぶ方向 | row |
| 親 | flex-wrap |
折り返すか | nowrap |
| 親 | justify-content |
主軸方向の配置と余白の配り方 | normal(flex-startと同じ動き) |
| 親 | align-items |
交差軸方向の配置 | normal(stretchと同じ動き) |
| 親 | align-content |
折り返した行どうしの配置 | normal |
| 親 | gap |
アイテム間の間隔 | normal(0と同じ動き) |
| 子 | flex |
伸びる・縮む・基準サイズをまとめて指定 | 0 1 auto |
| 子 | flex-grow |
余った幅を受け取る割合 | 0 |
| 子 | flex-shrink |
足りない幅を引き受ける割合 | 1 |
| 子 | flex-basis |
伸縮する前の基準サイズ | auto |
| 子 | align-self |
そのアイテムだけ交差軸の配置を変える | auto |
| 子 | order |
並び順(小さいほど前) | 0 |
| 子 | margin: auto |
余白をすべて受け取る | - |
display: flex の親は横幅いっぱいに広がり、display: inline-flex の親は中身の幅に合わせて縮みます。60pxの子2つと gap: 8px で確かめると、flexの親は800px(画面幅)、inline-flexの親は128pxになりました。
justify-content×align-itemsの全組み合わせ図
幅のある箱の中に3つのアイテム(1・2・3)を置いたときの配置図です。横がjustify-content、縦がalign-itemsによる位置を表しています。. は空きスペースです。
justify-content | align-items: | align-items: | align-items:
| flex-start | center | flex-end
------------------+-------------------+-------------------+------------------
| [123............] | [...............] | [...............]
flex-start | [...............] | [123............] | [...............]
| [...............] | [...............] | [123............]
------------------+-------------------+-------------------+------------------
| [......123......] | [...............] | [...............]
center | [...............] | [......123......] | [...............]
| [...............] | [...............] | [......123......]
------------------+-------------------+-------------------+------------------
| [............123] | [...............] | [...............]
flex-end | [...............] | [............123] | [...............]
| [...............] | [...............] | [............123]
------------------+-------------------+-------------------+------------------
| [1......2......3] | [...............] | [...............]
space-between | [...............] | [1......2......3] | [...............]
| [...............] | [...............] | [1......2......3]
------------------+-------------------+-------------------+------------------
| [..1....2....3..] | [...............] | [...............]
space-around | [...............] | [..1....2....3..] | [...............]
| [...............] | [...............] | [..1....2....3..]
------------------+-------------------+-------------------+------------------
| [...1...2...3...] | [...............] | [...............]
space-evenly | [...............] | [...1...2...3...] | [...............]
| [...............] | [...............] | [...1...2...3...]
align-itemsには、このほかに stretch(初期の動き)と baseline があります。
align-items: stretch(高さを指定していない子が、親の高さいっぱいに伸びる)
[123............]
[123............]
[123............]
align-items: baseline(文字の下端のラインで揃う)
[.2.............] 2 は文字が大きいアイテム
[123............] 1・2・3 の文字の下端が同じ高さに並ぶ
[...............]
justify-contentの実測値
幅300pxの親に、幅60pxの子を3つ入れたときの各アイテムの左端の位置(px)です。余っている幅は 300 − 60×3 = 120px です。
| justify-content | 1つ目 | 2つ目 | 3つ目 | 余白120pxの配り方 |
|---|---|---|---|---|
flex-start |
0 | 60 | 120 | すべて右側 |
center |
60 | 120 | 180 | 左右に60pxずつ |
flex-end |
120 | 180 | 240 | すべて左側 |
space-between |
0 | 120 | 240 | アイテムの間に60pxずつ(両端は0) |
space-around |
20 | 120 | 220 | 各アイテムの左右に20pxずつ(両端20px、間40px) |
space-evenly |
30 | 120 | 210 | 両端と間をすべて30pxで均等に |
space-aroundは両端の余白が間の半分、space-evenlyはすべて同じ幅になります。
align-itemsの実測値
高さ120pxの親に、高さの違う3つのアイテム(A:24px、B:文字を32pxにして48px、C:上に余白20pxを付けて44px)を入れたときの、上端の位置と高さです。
| align-items | A | B | C |
|---|---|---|---|
stretch |
上0・高さ120 | 上0・高さ120 | 上0・高さ120 |
flex-start |
上0・高さ24 | 上0・高さ48 | 上0・高さ44 |
center |
上48・高さ24 | 上36・高さ48 | 上38・高さ44 |
flex-end |
上96・高さ24 | 上72・高さ48 | 上76・高さ44 |
baseline |
上20・高さ24 | 上2・高さ48 | 上0・高さ44 |
stretch では3つとも親の高さ120pxまで伸びています。baseline では、文字の下端のラインが揃うように、それぞれの上端の位置が変わっています。
9方向の配置コード
1つの要素を箱の中の9か所に置くときの組み合わせです(幅300px・高さ120pxの親に、幅100px・高さ40pxの子を置いて位置を確認済み)。
| 置きたい位置 | justify-content | align-items | 子の左上の位置 |
|---|---|---|---|
| 左上 | flex-start |
flex-start |
(0, 0) |
| 上中央 | center |
flex-start |
(100, 0) |
| 右上 | flex-end |
flex-start |
(200, 0) |
| 左中央 | flex-start |
center |
(0, 40) |
| 中央 | center |
center |
(100, 40) |
| 右中央 | flex-end |
center |
(200, 40) |
| 左下 | flex-start |
flex-end |
(0, 80) |
| 下中央 | center |
flex-end |
(100, 80) |
| 右下 | flex-end |
flex-end |
(200, 80) |
コピペで使えるflexboxレイアウト集
ここからは、よく使う配置をHTMLとCSSのセットで載せます。クラス名を変えるだけでそのまま使える形にしています。
横並びにして間隔をあける
<ul class="tags">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
.tags {
display: flex;
gap: 12px; /* アイテムの間だけに12px */
list-style: none;
padding: 0;
margin: 0;
}
幅60pxの子3つで確かめると、左端の位置は 0・72・144px になりました。間隔はアイテムの間だけに入り、両端には付きません。
上下左右の中央に置く
<div class="center-box">
<p>中央に表示</p>
</div>
.center-box {
display: flex;
justify-content: center; /* 左右の中央 */
align-items: center; /* 上下の中央 */
min-height: 100vh; /* 画面の高さいっぱいにする(上下中央には高さが必要) */
}
800×600pxの画面に幅200px・高さ100pxの子を置くと、左上の位置は (300, 250) になり、ちょうど中央でした。子が1つだけなら、親を display: flex にして子に margin: auto を指定する書き方でも同じ位置になります。
縦に2つ以上を積んで全体を中央に置きたいときは、flex-direction: column を足します。
.center-stack {
display: flex;
flex-direction: column;
justify-content: center; /* 縦並びでは上下の中央 */
align-items: center; /* 縦並びでは左右の中央 */
gap: 8px;
min-height: 100vh;
}
両端に揃える(ヘッダー)
ロゴを左、メニューを右に置く定番の形です。
<header class="header">
<a class="logo" href="/">Logo</a>
<nav class="nav">
<a href="/about">会社情報</a>
<a href="/contact">お問い合わせ</a>
</nav>
</header>
.header {
display: flex;
justify-content: space-between; /* 両端に揃える */
align-items: center; /* 上下の中央 */
height: 56px;
padding: 0 16px;
}
.nav {
display: flex;
gap: 16px;
}
幅600px・高さ56pxで確かめると、幅80pxのロゴは左端(0)、幅140pxのメニューは左から460px、つまり右端にぴったり付きました。
1つだけ右に寄せる
「左にロゴと検索、右端にログインだけ」のように、途中から右に寄せたいときは、寄せたい子に margin-left: auto を指定します。
.toolbar {
display: flex;
align-items: center;
gap: 8px;
}
.toolbar .push-right {
margin-left: auto; /* 余っている幅をすべて左の余白として受け取る */
}
幅300pxの親に幅60pxの子を3つ入れ、3つ目に margin-left: auto を付けると、左端の位置は 0・68・240px になりました。3つ目だけが右端に移動しています。
折り返すカード(幅に合わせて列数が変わる)
<div class="cards">
<article class="card">カード1</article>
<article class="card">カード2</article>
<article class="card">カード3</article>
<article class="card">カード4</article>
<article class="card">カード5</article>
</div>
.cards {
display: flex;
flex-wrap: wrap; /* 入りきらない分は次の行へ */
gap: 16px;
}
.card {
flex: 1 1 200px; /* 基準200px。余れば伸び、足りなければ縮む */
}
幅500pxの親で確かめると、1行に2枚(各242px)が並び、5枚目は1枚だけで幅500pxいっぱいに伸びました。
| カード | 位置 | 幅 |
|---|---|---|
| 1枚目 | (0, 0) | 242px |
| 2枚目 | (258, 0) | 242px |
| 3枚目 | (0, 66) | 242px |
| 4枚目 | (258, 66) | 242px |
| 5枚目 | (0, 132) | 500px |
折り返すカード(3列に固定して最後の行も同じ幅にする)
最後の行のカードも同じ幅に保ちたいときは、伸びない設定(flex-grow: 0)にして、幅を計算で決めます。
.cards-3col {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.cards-3col .card {
/* (全体の幅 − 間隔2つ分)÷ 3 */
flex: 0 1 calc((100% - 16px * 2) / 3);
}
幅500pxの親では、カードは各156pxになり、4枚目と5枚目は2行目の左から順に並びました(位置は (0, 66) と (172, 66))。列数をきっちり決めたい一覧では、CSS Gridの grid-template-columns: repeat(3, 1fr) も同じ見た目を短く書けます。
フッターを画面の下に固定する
本文が短いページでも、フッターを画面の一番下に置く書き方です。
<body class="page">
<header>ヘッダー</header>
<main>本文</main>
<footer>フッター</footer>
</body>
.page {
display: flex;
flex-direction: column;
min-height: 100vh; /* 画面の高さ以上にする */
margin: 0;
}
.page > main {
flex: 1; /* 余った高さをすべて本文が受け取る */
}
min-height: 400px の親に、高さ50pxのヘッダーと高さ40pxのフッターを入れて確かめると、本文は高さ310pxまで伸び、フッターは上から360pxの位置、つまり下端にぴったり付きました。
等幅のカラムに分ける
.columns {
display: flex;
gap: 20px;
}
.columns > * {
flex: 1; /* 余った幅を同じ割合で分け合う */
min-width: 0; /* 中身が長くても等幅を保つ */
}
幅600pxで gap: 20px、子3つのとき、各カラムは186.7pxになりました((600 − 20×2) ÷ 3)。
サイドバー固定+メイン可変
.layout {
display: flex;
gap: 24px;
}
.sidebar {
flex: 0 0 200px; /* 伸びない・縮まない・幅200px */
}
.main {
flex: 1; /* 残りすべて */
min-width: 0;
}
幅800pxの親では、サイドバーが200px、メインが576px(800 − 200 − 24)になりました。
アイコン+1行で省略するテキスト
<div class="item">
<img class="icon" src="icon.png" alt="" width="40" height="40">
<div class="body">
<p class="title">長いタイトルが入っても1行で省略して表示します</p>
</div>
</div>
.item {
display: flex;
align-items: center;
gap: 8px;
}
.icon {
flex-shrink: 0; /* アイコンは縮めない */
}
.body {
flex: 1;
min-width: 0; /* これがないと中の文字が省略されずにはみ出す */
}
.title {
margin: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
min-width: 0 が必要な理由は、後半の「効かない原因」で実測値とあわせて説明します。
間隔はgapで指定する
アイテムどうしの間隔は、親に gap を書くのが最も手軽です。 marginで間隔をあける方法と比べると、両端の余白を打ち消す指定がいらなくなります。
| 書き方 | 意味 |
|---|---|
gap: 16px; |
縦横とも16px |
gap: 8px 20px; |
行の間8px、列の間20px(row-gap、column-gapの順) |
row-gap: 8px; |
行の間だけ |
column-gap: 20px; |
列の間だけ |
幅300pxの親で、幅140pxの子4つを flex-wrap: wrap; gap: 8px 20px; で並べると、位置は (0, 0)・(160, 0)・(0, 38)・(160, 38) になりました。列の間が20px、行の間が8pxです。
flexboxでのgapは、MDNのブラウザー対応データ(npmパッケージ @mdn/browser-compat-data 8.1.4)によると Chrome 84、Edge 84、Firefox 63、Safari 14.1(iOS Safari 14.5)以降で使えます。現在の主要ブラウザーではそのまま使える機能です。
gapとmarginの違い
| 比べる点 | gap | margin |
|---|---|---|
| 書く場所 | 親に1回 | 子すべて |
| 両端の余白 | 付かない | 付く(最後の子だけ0にする指定が必要) |
| 折り返したときの行間 | 自動で入る | 上下のmarginも別に必要 |
| space-betweenとの併用 | gapが「最小の間隔」になる | 余白に足される |
space-betweenと併用した例として、幅300px・子60px×3で justify-content: space-between; gap: 12px; と書くと、位置は 0・120・240px でした。余白が十分あるので間隔は60pxのままです。画面が狭くなって余白がなくなっても、12pxの間隔は確保されます。
なお、通常のブロック要素では上下に隣り合うmarginが重なって1つになります(marginの相殺)が、flexアイテムどうしのmarginは相殺されません。 下20pxと上20pxのmarginを持つ2つの子で確かめると、通常のブロックでは2つ目が上から50px、縦並びのflexでは70pxの位置になりました。
flex:1の伸縮計算を数値で理解する
flex は、flex-grow(伸びる割合)・flex-shrink(縮む割合)・flex-basis(基準サイズ)の3つをまとめて書くプロパティです。書き方ごとに実際に設定される値を、getComputedStyle で確認しました。
| 書き方 | flex-grow | flex-shrink | flex-basis | 動き |
|---|---|---|---|---|
| (指定なし) | 0 | 1 | auto | 伸びない・縮む・中身の幅が基準 |
flex: 1 |
1 | 1 | 0% | 伸びる・縮む・基準0 |
flex: auto |
1 | 1 | auto | 伸びる・縮む・中身の幅が基準 |
flex: none |
0 | 0 | auto | 伸びない・縮まない |
flex: 2 100px |
2 | 1 | 100px | 100pxを基準に2の割合で伸びる |
flex: 0 0 200px |
0 | 0 | 200px | 200px固定 |
計算の流れ
flexboxは、次の順番でアイテムの幅を決めます。
flowchart TD
A["各アイテムの基準サイズ flex-basis を合計する"] --> B{"親の幅(gapを引いた分)と比べる"}
B -- "余っている" --> C["余りを flex-grow の比で配る"]
B -- "足りない" --> D["不足分を flex-shrink × flex-basis の比で引く"]
B -- "ちょうど" --> E["基準サイズのまま"]
伸びる計算:flex-growの比で余りを配る
幅600pxの親に3つの子を入れ、flex: 1・flex: 2・flex: 1 と指定した例です。
- 基準サイズは3つとも0なので、余りは 600 − 0 = 600px
- flex-growの合計は 1 + 2 + 1 = 4
- 1つ分は 600 ÷ 4 = 150px
| アイテム | 指定 | 計算 | 実測の幅 |
|---|---|---|---|
| 1つ目 | flex: 1 |
0 + 150 × 1 | 150px |
| 2つ目 | flex: 2 |
0 + 150 × 2 | 300px |
| 3つ目 | flex: 1 |
0 + 150 × 1 | 150px |
flex:1とflex:autoの違い
同じ「伸びる」指定でも、基準サイズが0かautoかで結果が変わります。 中身の幅が100px・200px・100pxの子3つを、幅600pxの親に入れて比べました。
| 指定 | 基準サイズの合計 | 余り | 1つ目 | 2つ目 | 3つ目 |
|---|---|---|---|---|---|
flex: 1 |
0 | 600 | 200px | 200px | 200px |
flex: auto |
400(100+200+100) | 200 | 166.7px | 266.7px | 166.7px |
flex: none |
400 | (配らない) | 100px | 200px | 100px |
| 指定なし | 400 | (配らない) | 100px | 200px | 100px |
flex: 1は中身に関係なく等分します(幅そのものを比で分ける)。flex: autoは中身の幅を確保したうえで、余りだけを等分します(200 ÷ 3 ≒ 66.7pxずつ足される)。
等幅のカラムを作りたいときは flex: 1、中身の長さに応じた幅にしつつ余白を埋めたいときは flex: auto を選びます。
gapがあるときの計算
gapは先に親の幅から引かれます。幅600px、gap: 20px、子3つに flex: 1 のとき、配る幅は 600 − 20×2 = 560px、1つ分は 560 ÷ 3 ≒ 186.7px で、実測も186.7pxでした。
flex-growの合計が1未満のとき
flex-growの合計が1より小さい場合は、余りの全部ではなく、その割合ぶんだけが配られます。幅600pxの親に flex: 0.2 と flex: 0.3 の子を入れると、幅は120px(600×0.2)と180px(600×0.3)になり、残りの300pxは空いたままでした。
縮む計算:flex-shrink×flex-basisの比で引く
親の幅より基準サイズの合計が大きいときは、不足分を各アイテムから引きます。縮む量は「flex-shrink × flex-basis」の比で決まるので、同じflex-shrinkでも、基準サイズが大きいアイテムほど多く縮みます。
幅400pxの親に、基準サイズ300px・200px・100pxの子を入れた例です(合計600px、不足200px)。
| アイテム | flex-shrink × flex-basis | 比 | 縮む量 | 実測の幅 |
|---|---|---|---|---|
| 1つ目(300px) | 1 × 300 = 300 | 300/600 | 200 × 300/600 = 100 | 200px |
| 2つ目(200px) | 1 × 200 = 200 | 200/600 | 200 × 200/600 ≒ 66.7 | 133.3px |
| 3つ目(100px) | 1 × 100 = 100 | 100/600 | 200 × 100/600 ≒ 33.3 | 66.7px |
1つ目だけ flex-shrink: 2 にすると、比の分母が 2×300 + 200 + 100 = 900 に変わります。
| アイテム | flex-shrink × flex-basis | 縮む量 | 実測の幅 |
|---|---|---|---|
| 1つ目(shrink 2) | 600 | 200 × 600/900 ≒ 133.3 | 166.7px |
| 2つ目 | 200 | 200 × 200/900 ≒ 44.4 | 155.6px |
| 3つ目 | 100 | 200 × 100/900 ≒ 22.2 | 77.8px |
中身の幅より小さくは縮まない(min-width: auto)
flexアイテムには、初期状態で「中身の最小幅より小さくならない」という決まりがあります(min-width: auto)。この決まりが flex: 1 の等分にも影響します。
幅600pxの親に flex: 1 の子を3つ入れ、2つ目の中に幅300pxの要素を入れた例です。
| 指定 | 1つ目 | 2つ目(中に300pxの要素) | 3つ目 |
|---|---|---|---|
flex: 1 |
150px | 300px | 150px |
flex: 1; min-width: 0; |
200px | 200px | 200px |
flex: 1 だけでは、2つ目が中身の300pxを確保し、残りの300pxを他の2つで分けています。min-width: 0 を足すと、中身に関係なく200pxずつの等分になります(中身ははみ出すので、overflow: hidden などと組み合わせます)。
flexboxが効かない原因と直し方
「指定したのに動かない」ときに確認したい原因を、再現コードと実測値つきでまとめました。
| 症状 | 主な原因 | 直し方 |
|---|---|---|
| 横に並ばない・中央に寄らない | 親に display: flex がない |
親に display: flex を書く |
| 上下中央にならない | 親の高さが子と同じ | 親に height か min-height を指定 |
align-content が効かない |
折り返していない | align-items を使う、または flex-wrap: wrap を付ける |
| テキストが省略されずにはみ出す | min-width: auto |
子に min-width: 0 |
width を指定したのに狭くなる |
flex-shrink: 1 で縮んでいる |
flex: 0 0 幅 または flex-shrink: 0 |
| 縦並びにしたら中央寄せの向きが変わった | 主軸と交差軸が入れ替わった | justify-contentとalign-itemsを入れ替える |
justify-self が効かない |
flexboxでは無視される | margin-left: auto などを使う |
| 折り返した最後の行が両端に分かれる | space-between が行ごとに働く |
gap と幅の計算に切り替える |
| 中央寄せの中身が大きいと左が切れる | 両側に均等にはみ出す | justify-content: safe center |
| 縦並びの中でスクロールしない | min-height: auto |
子に min-height: 0 |
原因1:親に display: flex を指定していない
justify-contentやalign-itemsは親に書くプロパティで、その親が display: flex になっていることが前提です。
/* 直す前:display: flex がない */
.box {
width: 300px;
height: 120px;
justify-content: center;
align-items: center;
}
/* 直した後 */
.box {
display: flex;
width: 300px;
height: 120px;
justify-content: center;
align-items: center;
}
| 状態 | 子(幅100px・高さ40px)の位置 |
|---|---|
| 直す前 | (0, 0)(左上のまま) |
| 直した後 | (100, 40)(中央) |
動かしたい要素自身に justify-content を書いている場合も同じです。書く場所は「動かしたい要素の1つ上の親」と覚えておくと確認しやすくなります。開発者ツールでは、flexの親要素の横に「flex」というバッジが表示されるので、そこで見分けられます。
原因2:親に高さがない
align-items: center は、親の高さの中で子を上下中央に置きます。親に高さの指定がないと、親の高さは子と同じになり、動く余地がありません。
/* 直す前:親の高さは子と同じ40pxになる */
.box { display: flex; align-items: center; }
/* 直した後:高さを指定する */
.box { display: flex; align-items: center; height: 120px; }
| 状態 | 親の高さ | 子(高さ40px)の上端 |
|---|---|---|
| 直す前 | 40px | 0 |
| 直した後 | 120px | 40(上下中央) |
画面全体の中央に置きたいときは min-height: 100vh を使います。height: 100% は、さらにその親にも高さが指定されている場合に働きます。
原因3:align-itemsとalign-contentの混同
名前が似ていますが、役割が違います。
| プロパティ | 何を揃えるか | 折り返しなし(nowrap)のとき |
|---|---|---|
align-items |
各行の中でのアイテムの位置 | 効く |
align-content |
折り返した行のかたまり全体の位置 | 効かない |
幅300px・高さ120pxの親に子(高さ40px)を1つ入れて確かめました。
| 指定 | 子の上端 |
|---|---|
align-content: center(折り返しなし) |
0(効いていない) |
align-content: center + flex-wrap: wrap |
40(中央) |
align-items: center(折り返しなし) |
40(中央) |
折り返して2行になったときの違いも見てみます。幅300px・高さ200pxの親に、幅140px・高さ40pxの子を4つ入れた結果です。
| 指定 | 1行目の上端 | 2行目の上端 | 見え方 |
|---|---|---|---|
align-items: center |
30 | 130 | 親を上下2つに分け、それぞれの中央に置く |
align-content: center |
60 | 100 | 2行をくっつけたまま、全体を中央に置く |
1行のときはalign-items、複数行のかたまりを動かしたいときはalign-contentと使い分けます。
なお、flexではない通常のブロック要素でも、align-content: center で中身を上下中央に置けるようになっています(MDNのデータでは Chrome 123、Firefox 125、Safari 17.4 以降)。Chromium 141 で、display: flex なしの高さ120pxの箱に指定したところ、子の上端は40になりました。
原因4:min-width: auto ではみ出す
flex: 1 を指定したのにテキストが省略されず、親からはみ出す場合は、先ほどの min-width: auto が関係しています。
/* 共通:flexアイテム(.body)の中にある p に省略の指定を書いている */
.title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* 直す前 */
.body { flex: 1; }
/* 直した後 */
.body { flex: 1; min-width: 0; }
幅300pxの親に、幅40pxのアイコンと、長いURLを入れたテキスト領域(.body)を並べて確かめました。
| 状態 | テキスト領域の幅 | 親の中身の幅(scrollWidth) |
|---|---|---|
flex: 1 のみ |
915.1px | 963px(はみ出す) |
flex: 1; min-width: 0; |
252px | 300px(親の中に収まる) |
省略の指定(overflow: hidden)をflexアイテム自身に書いた場合は、min-widthの自動的な最小幅が0として扱われるため、min-width: 0 がなくても252pxに収まりました。はみ出すのは、flexアイテムの「中の要素」が長いときです。「flex: 1 と min-width: 0 はセット」と覚えておくと、長いテキストやコードブロック、表を含むレイアウトで役立ちます。縦並び(flex-direction: column)では同じことが高さで起こるので、min-height: 0 を使います。高さ200pxの縦並びの親で、高さ500pxの中身を持つ子に flex: 1 を指定すると、子の高さは500pxになって親からはみ出し、min-height: 0; overflow: auto; を足すと160pxに収まってスクロールできるようになりました。
原因5:widthを指定したのに狭くなる
flexアイテムは初期状態で flex-shrink: 1 なので、入りきらないときはwidthを指定していても縮みます。
| 指定 | 親300pxの中での幅 |
|---|---|
子2つに width: 200px |
150px・150px(縮んでいる) |
1つ目 flex: 0 0 200px、2つ目 flex: 1 |
200px・100px |
| 幅100pxの子5つ(折り返しなし) | 60pxずつ |
幅100pxの子5つに flex-shrink: 0 |
100pxずつ(親からはみ出して中身の幅は500px) |
幅を保ちたいアイテムには flex: 0 0 200px または flex-shrink: 0 を指定します。はみ出させたくない場合は、親に flex-wrap: wrap を付けて折り返します。
原因6:縦並びにしたら向きが変わった
flex-direction: column では、justify-contentが上下、align-itemsが左右を担当します。幅300px・高さ200pxの縦並びの親で確かめました。
| 指定 | 子(幅100px・高さ40px)の位置 | 動いた方向 |
|---|---|---|
justify-content: center |
(0, 80) | 上下 |
align-items: center |
(100, 0) | 左右 |
原因7:justify-selfやjustify-itemsが効かない
justify-self と justify-items はCSS Grid向けのプロパティで、flexboxでは無視されます(指定しても子の位置は (0, 0) のままでした)。flexboxで1つだけ主軸方向に動かしたいときは、margin-left: auto や margin-right: auto を使います。交差軸方向なら align-self が使えます。
原因8:折り返した最後の行が両端に分かれる
justify-content: space-between は行ごとに働くため、最後の行のアイテム数が少ないと、間が大きくあきます。幅500pxの親に幅150pxの子を5つ入れると、2行目は (0, 50) と (350, 50) に分かれました。左から順に詰めたいときは、コピペ集の「3列に固定」の書き方(gap と calc で幅を決める)にすると、2行目が (0, 66)・(172, 66) と左詰めになります。
原因9:中央寄せの中身が大きいと左側が見えなくなる
justify-content: center は、中身が親より大きいとき、左右に均等にはみ出します。 左側にはみ出した部分はスクロールでも表示できません。
| 指定(親200px・子300px・overflow: auto) | 子の左端 | スクロールできる幅 |
|---|---|---|
justify-content: center |
−50px(左に50pxはみ出す) | 50px |
justify-content: safe center |
0 | 100px(全体を表示できる) |
safe を付けると、はみ出すときだけ先頭揃えに切り替わります。MDNのデータでは Chrome 115、Firefox 63、Safari 17.6 以降で使えます。
よくある質問
Q. justify-contentとalign-itemsはどう覚えればよいですか? A. justify-contentは「並んでいる方向(主軸)」、align-itemsは「それと直角の方向(交差軸)」です。横並び(初期状態)なら、justify-contentが左右、align-itemsが上下になります。縦並びにすると入れ替わります。
Q. flex: 1 は何の略ですか?
A. flex: 1 1 0%、つまり flex-grow: 1、flex-shrink: 1、flex-basis: 0% の略です。基準サイズを0にして、親の幅を同じ割合で分け合う指定になります。
Q. gapとmarginはどちらを使えばよいですか?
A. アイテムどうしの間隔はgapが手軽です。親に1回書くだけで、両端に余白が付かず、折り返したときの行間も入ります。「1つだけ右に寄せる」のように特定のアイテムを動かしたいときは、margin-left: auto を使います。
Q. flexboxとCSS Gridはどう使い分けますか? A. 1方向に並べて、中身の量に合わせて伸び縮みさせたいときはflexbox、行と列の両方をそろえた格子状の配置にしたいときはGridが向いています。ヘッダーやボタンの並び、タグの一覧はflexbox、カードを決まった列数で並べる一覧やページ全体の枠組みはGrid、という分け方がよく使われます。
まとめ
- 親に
display: flexを書くと、直下の子が横に並ぶ。間隔は親のgapで指定する。 - justify-contentは主軸(横並びなら左右)、align-itemsは交差軸(横並びなら上下)。縦並びにすると入れ替わる。
- 上下左右の中央は
justify-content: center; align-items: center;。上下中央には親の高さが必要。 flex: 1は1 1 0%の略で、親の幅を比で分ける。flex: autoは中身の幅を確保してから余りを配る。- 縮む量は「flex-shrink × flex-basis」の比で決まり、幅を保ちたいアイテムには
flex: 0 0 幅を使う。 - 長いテキストがはみ出すときは
min-width: 0(縦並びならmin-height: 0)を足す。 - 効かないときは「親に書いているか」「親に高さがあるか」「折り返しの有無」の3点から確認する。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS flexboxの使い方早見表|横並び・中央寄せのコピペ集と効かない原因」
株式会社RJCでは、CSSのレイアウトの仕組みと書き方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。