Flexboxは2015年頃にすべての主要ブラウザに導入され、開発者が10年間回避策を講じてきた問題をすぐに解決しました。垂直中央揃えです。しかし、ほとんどの人は逆から学びました — なぜそれが機能するかを理解せずに、チートシートからjustify-content: centerを暗記しました。レイアウトが思い通りにならないとき、その理解のギャップが5分の作業を1時間の試行錯誤に変えてしまいます。このガイドでは、まずメンタルモデルを構築し、実際のプロジェクトで本当に重要なすべてのプロパティを解説します。
メンタルモデル:1度に1つの軸
Flexboxのコアコンセプトは、アイテムを1つの軸に沿って配置することです。アイテムが流れる方向である主軸と、垂直に走る交差軸があります。ほぼすべての初心者が見逃す重要な洞察:flex-directionがどちらの軸がどれかを決定します。それ以外のすべてはそこから導かれます。
/* Default: main axis runs LEFT → RIGHT, cross axis runs TOP → BOTTOM */
.container {
display: flex;
flex-direction: row; /* default */
}
/* Rotated: main axis now runs TOP → BOTTOM, cross axis runs LEFT → RIGHT */
.container {
display: flex;
flex-direction: column;
}
/*
justify-content → controls alignment on the MAIN axis
align-items → controls alignment on the CROSS axis
This is why centering something in both axes looks like this:
*/
.center-both {
display: flex;
justify-content: center; /* horizontally centred (main axis = row) */
align-items: center; /* vertically centred (cross axis) */
}flex-direction: columnに切り替えると、justify-contentは水平方向の配置を制御しなくなります — 主軸が回転したため、垂直方向の配置を制御します。align-itemsが水平方向を制御するようになります。何かが期待する場所に配置されないときは、いつもこの回転を念頭に置いてください。コンテナプロパティ
これらのプロパティは、display: flexを持つ親要素であるフレックスコンテナに設定します。すべての子アイテムがどのように配布・整列されるかを制御します。
/* display: flex makes the element a block-level flex container.
display: inline-flex makes it inline (sits in text flow). */
.nav {
display: flex;
}
/* flex-direction — which way does the main axis run? */
.nav {
flex-direction: row; /* left to right (default) */
flex-direction: row-reverse; /* right to left */
flex-direction: column; /* top to bottom */
flex-direction: column-reverse; /* bottom to top */
}
/* flex-wrap — what happens when items overflow the container? */
.card-grid {
flex-wrap: nowrap; /* all items forced onto one line (default) */
flex-wrap: wrap; /* items wrap onto additional lines */
flex-wrap: wrap-reverse; /* items wrap in reverse order */
}
/* gap — space between items. Modern approach; avoids margin hacks. */
.card-grid {
gap: 1.5rem; /* same in both directions */
gap: 1rem 2rem; /* row-gap column-gap */
}gapプロパティは特別な言及に値します。これが存在する前は、フレックスアイテムにマージンを追加し、外側の端をネガティブマージンでキャンセルするのが一般的なパターンでした。gapはそれをすべてきれいに置き換えます — 代わりにどこでも使用してください。
/* justify-content — alignment on the MAIN axis */
.nav {
justify-content: flex-start; /* packed to start (default) */
justify-content: flex-end; /* packed to end */
justify-content: center; /* packed to centre */
justify-content: space-between; /* first/last at edges, equal gaps between */
justify-content: space-around; /* equal space around each item */
justify-content: space-evenly; /* equal space between every gap */
}
/* align-items — alignment on the CROSS axis (single line) */
.nav {
align-items: stretch; /* items fill cross-axis height (default) */
align-items: flex-start;/* items align to start of cross axis */
align-items: flex-end; /* items align to end of cross axis */
align-items: center; /* items centred on cross axis */
align-items: baseline; /* items aligned by their text baseline */
}
/* align-content — cross-axis alignment when there are MULTIPLE lines
(only takes effect with flex-wrap: wrap and enough items to wrap) */
.card-grid {
flex-wrap: wrap;
align-content: flex-start; /* rows packed to top */
align-content: center; /* rows centred vertically */
align-content: space-between; /* rows spread out with space between */
}これらを組み合わせた実際のナビゲーションバーを示します。ロゴは左側にあり、ナビゲーションリンクはmargin-left: autoを使用して右側に押し出されています — 古典的なFlexboxのトリックです。justify-content: space-betweenアプローチも機能しますが、2つ以上のグループがある場合、オートマージンテクニックの方が柔軟です。
/* Nav: logo left, links right */
.site-nav {
display: flex;
align-items: center;
gap: 1rem;
padding: 0 2rem;
height: 64px;
background: #1a1a2e;
}
.site-nav .logo {
font-size: 1.25rem;
font-weight: 700;
color: #fff;
text-decoration: none;
}
.site-nav .nav-links {
display: flex;
align-items: center;
gap: 1.5rem;
margin-left: auto; /* pushes everything after it to the right */
list-style: none;
margin-top: 0;
margin-bottom: 0;
padding: 0;
}
.site-nav .nav-links a {
color: #ccc;
text-decoration: none;
font-size: 0.9rem;
}
.site-nav .nav-links a:hover {
color: #fff;
}アイテムプロパティ
これらのプロパティは、フレックスコンテナの直接の子であるフレックスアイテムに設定します。個々のアイテムがどのように成長、縮小、サイズ調整するかを制御します。
flex-grow— このアイテムが利用可能な空きスペースのどれだけを占めるか。デフォルトは0(成長しない)。アイテムに1を設定すると、残りのすべてのスペースを取得します。flex-shrink— スペースが不足しているときに、このアイテムが他のアイテムに比べてどれだけ縮小するか。デフォルトは1。アイテムが縮小しないようにするには0を設定します。flex-basis— 成長や縮小の前のアイテムの初期サイズ。長さ(250px、30%)またはauto(アイテムのコンテンツサイズを使用)を指定できます。align-self— 特定の1つのアイテムのalign-itemsを上書きします。同じ値を受け入れます:auto、flex-start、flex-end、center、baseline、stretch。order— HTMLに触れずにビジュアルオーダーを変更します。デフォルトは0。値が小さいほど最初に表示されます。控えめに使用してください — タブオーダーが壊れ、キーボードユーザーやスクリーンリーダーユーザーにアクセシビリティの問題を引き起こします。
/* Classic sidebar + main content layout */
.app-layout {
display: flex;
min-height: 100vh;
}
.sidebar {
flex: 0 0 280px; /* don't grow, don't shrink, always 280px wide */
background: #f5f5f5;
padding: 2rem 1.5rem;
}
.main-content {
flex: 1; /* grow to fill all remaining space */
padding: 2rem;
min-width: 0; /* critical: prevents content overflow in flex children */
}
/* Responsive: stack vertically on mobile */
@media (max-width: 768px) {
.app-layout {
flex-direction: column;
}
.sidebar {
flex: none; /* reset — don't use flex-basis on column layout */
}
}min-width: 0の落とし穴:デフォルトでは、フレックスアイテムは最小コンテンツサイズ以下に縮小できません。フレックスアイテム内に長い単語や幅の広いテーブルがある場合、折り返されずにオーバーフローします。フレックスアイテムにmin-width: 0を追加するとこれが修正されます。サイドバーレイアウトのメインコンテンツエリアで常に出てきます。flex省略記法の解説
flex省略記法は、flex-grow、flex-shrink、flex-basisを1つの宣言にまとめます。W3C仕様は一般的なケースをカバーするいくつかのキーワード値を定義しており、それらはよく混同されます。
/* flex: 1
Expands to: flex-grow: 1; flex-shrink: 1; flex-basis: 0%
Meaning: grow and shrink freely; start from zero (ignore content size).
All items with flex: 1 share space equally, regardless of content.
Most common choice for "fill available space". */
.tab { flex: 1; }
/* flex: auto
Expands to: flex-grow: 1; flex-shrink: 1; flex-basis: auto
Meaning: grow and shrink freely; start from the item's content size.
Items with more content get more space — proportional, not equal. */
.column { flex: auto; }
/* flex: none
Expands to: flex-grow: 0; flex-shrink: 0; flex-basis: auto
Meaning: completely rigid — don't grow, don't shrink, stay at content size.
Use for items that should never flex (icons, avatars, fixed labels). */
.avatar { flex: none; }
/* flex: 0 0 200px
Explicit: don't grow, don't shrink, always exactly 200px.
Same as writing out all three values. More readable for fixed-size items. */
.sidebar { flex: 0 0 200px; }
/* Practical difference: flex: 1 vs flex: auto in a tab bar
With flex: 1 → all tabs are equal width regardless of label length
With flex: auto → "Settings" tab is wider than "Home" tab */
.tabs { display: flex; }
.tab-equal { flex: 1; } /* equal width tabs */
.tab-auto { flex: auto; } /* content-sized tabs */一般的な実際のレイアウト
Flexboxだけで構築した、定期的に使用する4つのパターンを紹介します。
/* 1. Sticky footer
The footer always sits at the bottom, even on short pages.
body (or .app-shell) becomes a column flex container. */
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
main {
flex: 1; /* expands to push footer down */
}
footer {
/* stays at the bottom */
}/* 2. Centred modal / hero content
Both axes centred — the Flexbox vertical-centring party trick. */
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 2rem;
background: linear-gradient(135deg, #667eea, #764ba2);
}
.hero-content {
max-width: 640px;
text-align: center;
color: #fff;
}/* 3. Nav bar: logo left, links right */
.site-nav {
display: flex;
align-items: center;
padding: 0 2rem;
height: 64px;
}
.site-nav .nav-links {
margin-left: auto; /* auto margin consumes all free space to its left */
display: flex;
gap: 1.5rem;
list-style: none;
padding: 0;
margin-top: 0;
margin-bottom: 0;
}/* 4. Card row that wraps on mobile */
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card {
flex: 1 1 280px; /* grow and shrink, but never below 280px wide */
background: #fff;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
/* On wide screens: 3-4 cards per row.
On narrow screens: cards wrap into their own rows automatically.
No media query needed for the wrap itself — flex-wrap handles it. */FlexboxとGrid — どちらをいつ使うか
この質問は常に出てきますが、答えはほとんどの記事が示すよりシンプルです:Flexboxは1次元レイアウト用。CSS Gridは2次元レイアウト用。単一の行または単一の列にアイテムを配置している場合 — ナビゲーションバー、ボタングループ、カード行 — Flexboxが適切なツールです。行と列の両方を同時に制御する必要がある場合 — フルページレイアウト、フォトモザイク、フォームグリッド — 代わりにGridを使用してください。
実際には、同じプロジェクトで両方を使用します。Gridはページレベルの構造を処理します(ヘッダー、サイドバー、メイン、フッター)。Flexboxはそれらの領域内のコンポーネントを処理します(ナビゲーションバー、カードコンテンツ、モーダル内のボタンクラスター)。競合するのではなく、補完し合います。
flex-wrap: wrapでこれは可能ですが、同じビジュアル行のアイテムは互いに関係がありません — 高さは独立しています。Gridの暗黙的な行サイズ設定はこれを自動的に処理します。ラップされた行のカードがすべて同じ高さを持ち、かつカード間で内部要素が整列する必要がある場合、Gridの方がクリーンです。まとめ
Flexboxのメンタルモデルはこうです:方向を選び、どのプロパティがどの軸を制御するかを理解し、アイテムが成長・縮小・固定のどれをすべきかを選択する。それが分かれば、チートシートは頼り木ではなく参照ツールになります。MDNのFlexboxガイドはエッジケースの最良の参考書であり、CSS-Tricksの完全ガイドは最も役立つビジュアルチートシートです。本番環境での使用において、ブラウザサポートは事実上ユニバーサルです — プレフィックスは不要です。本当に混乱するエッジケースに遭遇した場合は、W3C仕様を一読する価値があります — アルゴリズムは正確に文書化されており、「なぜこのような動作をするのか」というほとんどの質問に答えています。