flex-wrap: 1 行か、必要なだけの行か
初期状態の flex コンテナは、すべてのアイテムを 1 行に置き (flex-wrap: nowrap)、収まるように縮めます。flex-wrap: wrap にすると、アイテムはサイズを保ったまま次の行に移ります:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>flex-wrap</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 13px; }
.box { display: flex; gap: 8px; width: 340px; padding: 8px; background: #e5e7eb; margin-bottom: 12px; }
.item { width: 100px; height: 36px; background: #2563eb; color: white; }
.wrap { flex-wrap: wrap; }
</style>
</head>
<body>
<code>flex-wrap: nowrap (default)</code>
<div class="box"><div class="item"></div><div class="item"></div><div class="item"></div><div class="item"></div><div class="item"></div></div>
<code>flex-wrap: wrap</code>
<div class="box wrap"><div class="item"></div><div class="item"></div><div class="item"></div><div class="item"></div><div class="item"></div></div>
<script>
document.querySelectorAll('.box').forEach((box) => {
box.children[0].textContent = Math.round(box.children[0].getBoundingClientRect().width) + 'px wide';
});
</script>
</body>
</html>Master CSS the hands-on way
Interactive lessons, real projects, and instant feedback.
START NOW
各アイテムは 100px を求め、それが 340px のボックスに 5 つあります。5 つのアイテムと 8px のすき間 4 つで 532px 必要なので、折り返しがないと、flex アイテムは初期状態で縮むため、それぞれ約 62px に押しつぶされます。wrap なら 100px のままで、1 行目に 3 つが収まり、残りの 2 つは 2 行目に移ります。
flex-wrap の値
値 動き nowrap (初期値)1 行。アイテムは縮み、それ以上縮めなくなるとコンテナからはみ出す wrap収まらないアイテムは下に新しい行を作る wrap-reverse同じだが、新しい行は上に積まれる。1 行目が一番下になる
アイテムの折り返しを見る
スライダーをドラッグして、コンテナの幅を変えてください。表示欄が行の数と、各行のアイテムの数を示します:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Wrap slider</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 14px; }
#box { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px; background: #e5e7eb; margin: 10px 0; }
.item { width: 90px; height: 40px; background: #16a34a; color: white; display: flex; align-items: center; justify-content: center; }
</style>
</head>
<body>
<label>container width <input id="w" type="range" min="120" max="620" value="400"> <span id="wv"></span></label>
<div id="box"></div>
<p id="out"></p>
<script>
const box = document.getElementById('box');
for (let i = 1; i <= 6; i++) box.insertAdjacentHTML('beforeend', '<div class="item">' + i + '</div>');
const update = () => {
const w = document.getElementById('w').value;
box.style.width = w + 'px';
document.getElementById('wv').textContent = w + 'px';
const lines = {};
[...box.children].forEach((c) => { const top = Math.round(c.getBoundingClientRect().top); lines[top] = (lines[top] || 0) + 1; });
const counts = Object.values(lines);
document.getElementById('out').textContent = counts.length + ' line(s): ' + counts.join(' + ') + ' items';
};
document.getElementById('w').addEventListener('input', update);
update();
</script>
</body>
</html>
400px では、90px のアイテム 4 つと 8px のすき間 3 つ (384px) が 1 行に収まるので、4 + 2 になります。620px の方へドラッグすると 6 つすべてが 1 行に収まり、120px の方へドラッグすると各アイテムが 1 行ずつになります。
flex-direction: 横並びか縦並びか
flex-direction はアイテムが並ぶ方向、つまり 主軸 を決めます:
値 アイテムの並び 最初のアイテム row (初期値)横に、書字方向に 行の始まり row-reverse横に、逆順に 行の終わり column縦に、上から下へ 一番上 column-reverse縦に、下から上へ 一番下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>flex-direction</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 13px; }
.grid { display: flex; flex-wrap: wrap; gap: 16px; }
.box { display: flex; gap: 4px; padding: 6px; background: #e5e7eb; width: 160px; height: 110px; margin-top: 4px; }
.box div { background: #2563eb; color: white; padding: 4px 10px; }
</style>
</head>
<body>
<div class="grid">
<div><code>row</code><div class="box" style="flex-direction: row"><div>1</div><div>2</div><div>3</div></div></div>
<div><code>row-reverse</code><div class="box" style="flex-direction: row-reverse"><div>1</div><div>2</div><div>3</div></div></div>
<div><code>column</code><div class="box" style="flex-direction: column"><div>1</div><div>2</div><div>3</div></div></div>
<div><code>column-reverse</code><div class="box" style="flex-direction: column-reverse"><div>1</div><div>2</div><div>3</div></div></div>
</div>
</body>
</html>
2 つの row のボックスでは、align-items: stretch が行と直角の方向に働くので、アイテムはボックスの高さいっぱいに伸びます。column のボックスでは、同じ理由で 幅 いっぱいに伸びます。軸が回転し、配置のプロパティもすべて一緒に回転したのです (justify-content のページ で詳しく見られます)。
flex-flow: 2 つを 1 行で
flex-flow は、flex-direction、flex-wrap の順に書くショートハンドです:
.cards { flex-flow: row wrap; } /* flex-direction: row; flex-wrap: wrap; */
.stack { flex-flow: column nowrap; } /* flex-direction: column; flex-wrap: nowrap; */
メディアクエリなしで wrap を使うレスポンシブなカード
各アイテムに flex: 1 1 180px で出発点のサイズを与え、行を折り返させます。各アイテムは行を埋めるように伸び、行にもう 1 つ 180px のアイテムが入らなくなると、次のアイテムが折り返します:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Wrapping cards</title>
<style>
body { font-family: system-ui, sans-serif; }
.cards { display: flex; flex-wrap: wrap; gap: 12px; }
.card {
flex: 1 1 180px; /* grow, shrink, start at 180px */
padding: 14px;
border: 1px solid #e5e7eb;
border-radius: 8px;
background: #f9fafb;
}
</style>
</head>
<body>
<div class="cards">
<div class="card">One</div>
<div class="card">Two</div>
<div class="card">Three</div>
<div class="card">Four</div>
<div class="card">Five</div>
</div>
</body>
</html>
幅約 800px のプレビューでは、1 行目に 3 枚のカード (それぞれ約 253px) が収まり、残りの 2 枚が 2 行目を分け合って、それぞれ約 386px まで伸びます。これが flexbox の動き方です。各行が自分のスペースを分けるので、短い最後の行のカードは上の行より広くなります。最後のカードもほかと同じ幅にしたいなら、代わりに grid と repeat(auto-fill, minmax(180px, 1fr)) を使います (grid のページ を参照)。
align-content: 行と行の間隔
コンテナが折り返していて、行の合計より高いとき、行をどこに置くかを決めるのが align-content です。justify-content と同じ値に加えて stretch を使えます:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>align-content</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 13px; }
.box { display: flex; flex-wrap: wrap; gap: 6px; width: 200px; height: 160px; background: #e5e7eb; }
.box div { width: 60px; height: 30px; background: #f59e0b; }
.row { display: flex; gap: 16px; }
</style>
</head>
<body>
<div class="row">
<div><code>align-content: flex-start</code><div class="box" style="align-content: flex-start"><div></div><div></div><div></div><div></div><div></div></div></div>
<div><code>align-content: space-between</code><div class="box" style="align-content: space-between"><div></div><div></div><div></div><div></div><div></div></div></div>
</div>
</body>
</html>
1 つ目のボックスでは、2 つの行がどちらも上にあります。2 つ目では 1 行目が上、2 行目が下にあり、余った高さはすべてその間に入ります。
逆順とアクセシビリティ
row-reverse、column-reverse、wrap-reverse は、アイテムが描かれる位置を変えるだけです。スクリーンリーダーと Tab キーは HTML の順番に従うので、キーボードで操作する人は、見た目と逆の方向にアイテムを移動します。逆順は見た目の効果のためだけに使い、順番に意味があるときは HTML で変えましょう。
よくある間違い
アイテムが折り返さずに縮む。 flex: 1 のアイテムは flex-basis 0 から始まり、1 行に押し込まれます。flex: 1 1 200px のように本当の basis を与えましょう。
flex-wrap をアイテムに書く。 flex コンテナに書きます。
折り返した行の間隔を align-items で調整しようとする。 それは各行の中でアイテムを揃えるものです。行そのものは align-content で動きます。
最後に 1 つだけ残ったアイテムが行全体に引き伸ばされる。 アイテムが 1 つの行での flex-grow の結果です。すべてのカードを同じ幅にしたいなら grid を使いましょう。
flex-direction: column が高さを埋めると思う。 縦並びのコンテナは、height を与えない限り内容と同じ高さしかないので、justify-content が働く余地がありません。