Flexbox実用パターン|中央寄せ・ナビ・等高カードを崩さない
Flexboxの中央寄せ、両端+中央のナビ、等高カードをコピペで動くコードで紹介。横スクロールが消えないmin-width:0問題も実例で直します。
ボタンを画面の真ん中に置きたいだけだったんです。
margin: 0 auto を足し、text-align: center も足し、なぜか効かないので position: absolute まで持ち出して、気づけば30分。最後に display: flex と justify-content: center の2行を書いたら、一瞬で終わりました。あのときの「先に知っておけば…」という脱力感、僕は今でも覚えています。
Flexboxは覚えることが多そうに見えて、実際に毎日使うのは6パターンくらいです。中央寄せ、両端に寄せるナビ、高さの揃ったカード、はみ出したら折り返す、要素を伸ばす・縮ませる、そして横スクロールを止める。この6個を手に覚えさせれば、CSSの「効かない地獄」からはほぼ抜けられます。
この記事では、その実用パターンをコピペで動くコードと一緒に並べます。ページ全体の設計やブレークポイントの切り方はClaude Codeレスポンシブデザインに、格子状に整列させたいときの使い分けはCSS Grid実務ガイドに分けてあるので、ここでは「同じ行・同じ列に並ぶ部品をどう御すか」だけに絞ります。
この記事の要点
- 中央寄せは
display: flex+justify-content: center+align-items: centerの3行。縦も横も一発で決まる。 - 両端+中央のナビは、ロゴ・リンク群・CTAを別々のflexアイテムにして
justify-content: space-between。中央寄せは内側のリンク群だけに掛ける。 - カードの高さを揃えるなら、外側は
flex-wrapで折り返し、内側を縦flexにして最後のボタンにmargin-top: auto。 - 折り返しは
flex-wrap: wrapとgapをセットで使う。子のmarginで余白を作ると折り返したとき崩れる。 - 「横スクロールが消えない」の9割は
min-width: 0の付け忘れ。flexアイテムは初期状態で中身より小さく縮まない。
main軸とcross軸だけ先に押さえる
Flexboxで迷う原因は、ほぼ「どっちの軸の話をしているか」を見失うことです。ここだけ先に整理します。
display: flex を付けた親が flexコンテナ、その直下の子が flexアイテム です。アイテムが流れる方向を 主軸(main軸)、それと直角の方向を 交差軸(cross軸) と呼びます。flex-direction: row(初期値)なら主軸は横、column なら主軸は縦になります。
そして、揃え方のプロパティは軸とセットで覚えると混乱しません。
| プロパティ | 効く軸 | 役割 | よく使う値 |
|---|---|---|---|
justify-content | 主軸 | 主軸方向の並べ方 | center / space-between / flex-start |
align-items | 交差軸 | 交差軸方向の揃え | center / stretch / flex-start |
gap | 両方 | アイテム間の余白 | 16px / 8px 16px |
flex-wrap | 主軸 | 入り切らないとき折り返す | wrap |
flex-direction: row のときは「justify-content が横、align-items が縦」。column にすると主軸と交差軸が入れ替わるので、この2つの担当も入れ替わります。ここだけ体に入れておくと、後のパターンが全部同じ理屈で読めます。公式の定義はMDNのフレックスボックスの基本概念が一番素直です。
パターン1:中央寄せ(縦も横も一発)
冒頭でやらかしたやつです。要素をコンテナの中央に置くなら、margin でも position でもなく、親をflexにします。
.center-box {
display: flex;
justify-content: center; /* 主軸(横)方向に中央 */
align-items: center; /* 交差軸(縦)方向に中央 */
min-height: 200px; /* 縦中央を見るために高さを与える */
}
ポイントは、縦中央を確認したいなら親に高さ(min-height や height)が要ることです。高さが中身ぴったりだと、align-items: center を書いても見た目が変わらず「効かない」と勘違いします。僕が30分溶かした原因の半分はこれでした。
横並びの複数要素を「グループごと中央、要素間は等間隔」にしたいなら、gap を足すだけです。justify-content: center と gap: 12px の組み合わせは、ボタン2つ並べるフッターなどで毎回使います。
パターン2:両端+中央のナビバー
ナビは「左にロゴ、中央にリンク、右にCTA」が定番です。ここで全体に justify-content: space-between を1回だけ掛けると、要素が3つあるので「ロゴ|リンク|CTA」が均等に離れます。でもリンクが増えると中央のかたまりが崩れます。
崩さないコツは、リンク群を1つのflexアイテムにまとめてしまうことです。外側は3要素(ロゴ/リンク群/CTA)として space-between、中央のリンク群だけ内側で justify-content: center を掛ける。役割を分けると、リンクが何本に増えても両端は動きません。
.nav {
display: flex;
align-items: center;
justify-content: space-between; /* ロゴ・リンク群・CTAを両端と中央へ */
gap: 16px;
flex-wrap: wrap;
}
.nav__logo,
.nav__cta {
flex: 0 0 auto; /* ロゴとCTAは縮ませない・伸ばさない */
}
.nav__links {
display: flex; /* リンク群を内側で1つのflexに */
justify-content: center;
gap: 16px;
flex: 1 1 auto; /* 余った幅はリンク群が引き受ける */
min-width: 0; /* 後述。これが無いと折り返さず溢れる */
}
CTAだけ縮ませたくないときは flex: 0 0 auto を、逆に検索バーのように余白を全部食わせたい要素には flex: 1 1 auto を当てます。「伸びてほしい要素」と「形を保ちたい要素」を指定で分けるのがナビ崩れ防止の本質です。
パターン3:高さの揃ったカード
カードを横に並べると、本文の量がバラバラで高さが揃わず、ボタンの位置がガタつきます。Flexboxはこれを2段構えで解きます。
外側のコンテナは普通に flex-wrap で折り返します。align-items の初期値は stretch なので、同じ行に並んだカードの高さは自動でいちばん高いものに揃います。揃わないように見えるのは、たいてい中のボタンの位置だけがズレているからです。
そこで内側です。カード自身を flex-direction: column の縦flexにして、最後のボタンに margin-top: auto を付けます。auto マージンは余った空間を全部吸うので、ボタンが下端にピタッと張り付き、行内で位置が揃います。
.card {
display: flex;
flex-direction: column; /* カード内を縦に積む */
gap: 8px;
padding: 20px;
border: 1px solid #d9e2ec;
border-radius: 8px;
min-width: 0;
}
.card__button {
margin-top: auto; /* 残り空間を吸ってボタンを下端へ */
align-self: flex-start;
}
これは「複数行に折り返したカード同士まで全部同じ高さに」という用途には向きません。行をまたいだ厳密な格子が要るならCSS Grid実務ガイドの出番です。Flexboxは「1行内の高さ揃え+ボタン位置揃え」が得意分野、と割り切ると判断が速くなります。
パターン4:折り返しは flex-wrap と gap をセットで
スマホで横スクロールを出さない一番簡単な方法が、flex-wrap: wrap です。入り切らないアイテムを次の行へ自動で送ります。ここで必ずペアにしたいのが gap です。
昔は子要素に margin-right を付けて間隔を作っていました。でも折り返すと、行末や最終行に余白が残って右端が揃いません。gap は「アイテムとアイテムの間」だけに余白を入れるので、何行に折り返しても端が揃います。横方向と縦方向で間隔を変えたいなら gap: 8px 16px(縦8px/横16px)と書けます。
.tag-row {
display: flex;
flex-wrap: wrap; /* 入り切らなければ次の行へ */
gap: 8px 12px; /* 縦8px・横12px。子のmarginは使わない */
}
flex-wrap と gap をセットにするだけで、タグ一覧・ボタン群・カード一覧の「スマホで横にはみ出す」がほぼ消えます。gap の挙動の細部はMDNのgapプロパティに表でまとまっています。
パターン5:flex-grow / shrink / basis を使い分ける
flex: 1 を何にでも付ける人をよく見ます(昔の僕です)。便利なんですが、ロゴやアイコンまで不自然に伸びて事故ります。中身を分解して理解すると、当て所が分かります。
flex: 1 1 220px は3つの値の一括指定で、それぞれ意味があります。
| 値 | 正式名 | 意味 |
|---|---|---|
| 1番目 | flex-grow | 余白があるとき、どれだけ伸びるか(0で伸びない) |
| 2番目 | flex-shrink | 幅が足りないとき、どれだけ縮むか(0で縮まない) |
| 3番目 | flex-basis | 伸び縮みする前の基準幅 |
つまり flex: 1 1 220px は「まず220pxを目安に、余れば伸び、足りなければ縮む」。flex: 0 0 auto は「伸びも縮みもせず中身の幅を保つ」。入力欄やカードには前者、ボタンやロゴには後者、と当てます。flex の各値の正式な扱いはMDNのflexプロパティが一次情報です。
実務でよく使うのが、フォームの「入力欄は伸ばす・ボタンは固定」です。input に flex: 1 1 16rem、button に flex: 0 0 auto を当てると、横幅が変わっても入力欄だけが伸縮し、ボタンは押しやすい幅のまま残ります。
パターン6:横スクロールが消えない min-width:0 問題
ここがFlexbox最大のハマりどころです。「flex-wrap も入れたのに横スクロールが消えない」――この相談の9割は同じ原因です。
flexアイテムは初期値で min-width: auto、つまり 中身より小さくは縮まない という性質を持ちます。だから長い英単語、URL、メールアドレス、claude-code-flexbox-patterns のようなスラッグが入ると、そのアイテムが縮まずに親をぐいぐい押し広げ、横スクロールが出ます。
直し方は2点セットです。縮ませたいアイテムに min-width: 0 を足し、テキストには overflow-wrap: anywhere を足す。これで「中身が長くても折り返してよい」という許可をブラウザに与えられます。
.card {
min-width: 0; /* これでカードが中身より小さく縮める */
}
.card p,
.card h3 {
overflow-wrap: anywhere; /* 長いURL・英単語を途中で折り返す */
}
僕がこれで何度もやられたのは、テスト時に日本語の短いダミーしか入れていなかったからです。検証するときは、わざと長い英語URLやメールアドレスを流し込んでください。本番でユーザーが入れた瞬間に崩れる、が一番痛い。
コピペで動く最小デモ(HTML+CSS)
ここまでの中央寄せ・ナビ・等高カード・折り返し・伸縮・min-width: 0 を1ファイルに詰めました。index.html として保存し、ブラウザで開くだけで動きます。ウィンドウ幅を狭めると、カードが折り返し、横スクロールが出ないのが確認できます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Flexbox実用パターン</title>
<style>
* { box-sizing: border-box; }
body {
margin: 0;
font-family: system-ui, sans-serif;
color: #172026;
background: #f6f8fb;
}
.wrap { width: min(1000px, 100% - 32px); margin: 0 auto; padding: 24px 0; }
/* パターン2:両端+中央のナビ */
.nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
padding: 12px 16px;
background: #fff;
border: 1px solid #d9e2ec;
border-radius: 8px;
}
.nav__logo, .nav__cta { flex: 0 0 auto; font-weight: 700; }
.nav__links {
display: flex;
justify-content: center;
gap: 16px;
flex: 1 1 auto;
min-width: 0; /* これが無いとリンクが折り返さず溢れる */
flex-wrap: wrap;
}
.nav__cta {
padding: 8px 14px; color: #fff; background: #0f766e; border-radius: 8px;
}
/* パターン1:中央寄せ */
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 160px; /* 縦中央を見るための高さ */
margin: 18px 0;
background: #e8f5f3;
border-radius: 8px;
}
/* パターン4:折り返し + パターン3:等高カード */
.cards { display: flex; flex-wrap: wrap; gap: 16px; }
.card {
display: flex;
flex-direction: column;
gap: 8px;
flex: 1 1 220px; /* パターン5:220pxを基準に伸縮 */
min-width: 0; /* パターン6:中身が長くても縮める */
padding: 20px;
background: #fff;
border: 1px solid #d9e2ec;
border-radius: 8px;
}
.card p { overflow-wrap: anywhere; margin: 0; }
.card__button {
margin-top: auto; /* ボタンを下端に揃える */
align-self: flex-start;
padding: 8px 14px;
border: 1px solid #0f766e; color: #0f766e; border-radius: 8px;
text-decoration: none;
}
</style>
</head>
<body>
<main class="wrap">
<nav class="nav">
<span class="nav__logo">ClaudeCodeLab</span>
<div class="nav__links">
<a href="#">Home</a><a href="#">Blog</a><a href="#">Docs</a>
</div>
<a class="nav__cta" href="#">相談する</a>
</nav>
<section class="hero">
<strong>真ん中に置きたいだけ、を3行で。</strong>
</section>
<section class="cards">
<article class="card">
<h3>短いカード</h3>
<p>本文が短くてもボタンは下端で揃います。</p>
<a class="card__button" href="#">読む</a>
</article>
<article class="card">
<h3>長文を含むカード</h3>
<p>https://developer.mozilla.org/ja/docs/Web/CSS/CSS_flexible_box_layout</p>
<a class="card__button" href="#">読む</a>
</article>
<article class="card">
<h3>もう一枚</h3>
<p>幅を狭めると、このカードは次の行へ折り返します。</p>
<a class="card__button" href="#">読む</a>
</article>
</section>
</main>
</body>
</html>
2枚目のカードにわざと長いURLを入れてあります。min-width: 0 と overflow-wrap: anywhere を消すと、その瞬間に横スクロールが復活するので、効果を体感したい人は試してみてください。読み上げやフォーカス順まで整えたいときはClaude Codeアクセシビリティ対応も合わせて見ておくと安全です。
Claude Codeに頼むときの一言
このパターンは、Claude Codeに実装を任せるときの「指定の語彙」としても効きます。「いい感じにして」だと、長文検証や最小幅まで面倒を見てくれません。僕は依頼文に必ずこの4語を入れます。
- 折り返し:「
flex-wrapとgapで折り返す」と書く。marginでの余白管理を避けさせる。 - 最小幅:「縮む要素には
min-width: 0を入れて」と明記する。横スクロール事故の予防線。 - 長文検証:「長い英語URLとメールアドレスを入れて360px幅で確認して」と検証データまで指定する。
- 伸縮の分担:「伸ばす要素と形を保つ要素を
flexで分けて」と役割を言語化する。
出てきたコードは、必ず幅を狭めて自分の目で確認します。短いダミーで通ったCSSは、本番データで崩れる。これは何度もやられた教訓です。
よくある質問
Q. FlexboxとGrid、どっちを使えばいい? A. ナビ、ボタン列、フォーム、1行のカードのように「一方向に並べて伸縮させたい」ならFlexbox。料金表や画像ギャラリーのように「行も列も揃った格子」が要るならGridです。使い分けの詳細はCSS Grid実務ガイドにまとめています。
Q. justify-content: center を書いたのに横中央にならない。
A. flex-direction: column になっていませんか。column だと主軸が縦に変わるので、justify-content は縦方向の制御になります。横中央にしたいなら align-items: center を使うか、flex-direction を row に戻します。
Q. align-items: center で縦中央が効かない。
A. 親に高さがないのが原因です。中身ぴったりの高さだと中央寄せの余地がありません。min-height を与えると効きます。
Q. カードの高さが揃わない。
A. 同じ行なら align-items の初期値 stretch で高さは揃っているはずです。ズレて見えるのはボタン位置の問題が多いので、カードを縦flexにしてボタンに margin-top: auto を当ててください。
Q. flex: 1 を全部に付けるのはダメ?
A. 伸ばしたい要素には便利ですが、ロゴやアイコンに付けると不自然に伸びます。形を保ちたい要素は flex: 0 0 auto、伸縮してよい要素は flex: 1 1 220px のように分けるのがおすすめです。
実際に試した結果
上のHTMLをローカルに保存し、ウィンドウ幅を1024px・720px・360pxと狭めて確認しました。カードは3列から2列、1列へ自然に折り返し、ナビのリンク群も溢れずに折り返します。2枚目に仕込んだ長いURLは、min-width: 0 と overflow-wrap: anywhere がある状態では折り返し、消すと即座に横スクロールが復活しました。冒頭の「中央寄せに30分」も、display: flex と justify-content: center の2行で終わる話だったと再確認できました。
結局Flexboxは、暗記すべきプロパティの一覧ではなく、「どっちの軸の話か」「伸ばすのか形を保つのか」の2つの判断に集約されます。この記事の6パターンを手元の型として持っておけば、レイアウトで悩む時間はかなり減るはずです。ページ全体の設計に広げるならClaude Codeレスポンシブデザインへ、コピペで使える実装の型を増やしたいなら教材一覧を、チームのUI実装ルールを整えたいなら研修・相談を覗いてみてください。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeに1ファイルだけ直させる指示文のつくり方
「もっと良くして」で40行も変えられた失敗から学んだ、触る範囲・検証・戻し方をセットにしたClaude Code用の依頼文テンプレートを紹介します。
Claude Code の権限拒否から復旧する: 止まった理由を次の安全手順に変える
Claude Code のコマンドが拒否されたとき、焦って許可を広げずに、拒否理由、代替手順、証拠コマンド、再試行条件へ分解する方法。
Claude Codeにビルド→スモークテスト→自動修正を回させる足場の作り方
最小スモークテストの選び方、失敗ログを食わせて直させるループ、回数上限と確認ゲートで暴走を止める方法を、コピペで動くコード付きで紹介します。