CSSフレックスボックス:ビジュアルジェネレーターで数分でどんなレイアウトも構築
📷 Sai Kiran Anagani / PexelsCSSフレックスボックス:ビジュアルジェネレーターで数分でどんなレイアウトも構築
flex-direction、justify-content、align-items — ライブビジュアルプレイグラウンドで各プロパティの動作を確認。一般的なレイアウトレシピ付き。
フレックスボックスとの出会い(そして今も調べる理由)
フレックスボックスを理解したと思った瞬間を覚えています。午後いっぱいナビゲーションバーと格闘していて、フロートは思い通りに動かず、inline-blockは幽霊スペースを追加していた。そこでStack Overflowのコメントで「フレックスボックスを使えばいい」と言われました。やってみると、display: flex と入力しただけで全部揃いました。魔法のようでした。
翌日、何かを縦方向に中央揃えしようとしたら、また迷子になりました。
これがフレックスボックスの性質です — 入口は簡単に感じますが、メンタルモデルの習得には時間がかかります。私がついに理解できたのは、「左、右、上、下」という考え方をやめ、「軸」という観点で考えるようになった時でした。その切り替えが起きると、フレックスボックスはCSSで最も満足感のあるツールの一つになりました。
実験しながら読みたい場合は、ToolBox HubsのCSSフレックスボックスジェネレーターをご利用ください — プロパティを調整してリアルタイムで結果を確認でき、メンタルモデルの構築を大幅に速めます。
フレックスコンテナモデル
フレックスボックスはすべて1つのルールから始まります:コンテナとその内部のアイテムがあります。コンテナに display: flex を設定すると、直接の子要素がフレックスアイテムになります。これがすべての階層です — コンテナとアイテム。
.container {
display: flex;
}
この1行で多くが変わります。アイテムはデフォルトで行に並び、コンテナの高さに合わせて引き伸ばされ、スペースが足りなければ縮小します。フレックスボックスプロパティのほとんどは、アイテムではなくコンテナに設定します。
2つの軸
これがフレックスボックスを学ぶほぼ全員が混乱する部分で、内面化すべき最も重要な概念です。フレックスボックスは2つの軸で動作します:
- メイン軸 — アイテムが流れる方向(行または列)
- クロス軸 — メイン軸に垂直
flex-direction が row(デフォルト)の場合、メイン軸は左から右へ、クロス軸は上から下へ走ります。column に切り替えると、それらが反転します。これは justify-content と align-items が絶対的な方向ではなく、これらの軸に対して相対的に定義されているため非常に重要です。
justify は常に「メイン軸に沿って」、align は常に「クロス軸に沿って」を意味すると覚えれば、残りすべてが予測可能になります。
実際に必要なすべてのプロパティ
flex-direction
アイテムが流れる方向を制御します。
.container {
display: flex;
flex-direction: row; /* デフォルト — 左から右 */
flex-direction: row-reverse; /* 右から左 */
flex-direction: column; /* 上から下 */
flex-direction: column-reverse; /* 下から上 */
}
column は思ったより頻繁に使います。縦方向にスタックしてスペースを制御したい時はいつでも、flex-direction: column と gap の組み合わせは素晴らしいです。
justify-content
メイン軸に沿ってアイテムを整列します。行では水平、列では垂直です。
.container {
display: flex;
justify-content: flex-start; /* デフォルト — 始点にアイテム */
justify-content: flex-end; /* 終点にアイテム */
justify-content: center; /* 中央にアイテム */
justify-content: space-between; /* アイテム間に均等なスペース、端には無し */
justify-content: space-around; /* 各アイテムの周りに均等なスペース */
justify-content: space-evenly; /* どこでも真に均等なスペース */
}
space-between はナビゲーションバーに最もよく使います — アイテムが両端に広がり、間に均等なギャップができます。center は何かを中央に配置したい時に使います。
align-items
クロス軸に沿ってアイテムを整列します。行では垂直、列では水平です。
.container {
display: flex;
align-items: stretch; /* デフォルト — アイテムをコンテナの高さに合わせて引き伸ばす */
align-items: flex-start; /* アイテムを上端に配置 */
align-items: flex-end; /* アイテムを下端に配置 */
align-items: center; /* アイテムを縦方向の中央に配置 */
align-items: baseline; /* テキストのベースラインでアイテムを整列 */
}
stretch がデフォルトというのは実際かなり便利です — コンテンツ量が異なっても、行内のフレックスアイテムが同じ高さになる理由です。縦方向の中央揃えが必要な時は align-items: center を使います。
flex-wrap
デフォルトでは、フレックスアイテムは1行に収まろうとして縮小します。flex-wrap でその動作を変更できます。
.container {
display: flex;
flex-wrap: nowrap; /* デフォルト — アイテムは1行に留まる */
flex-wrap: wrap; /* アイテムが新しい行に折り返す */
flex-wrap: wrap-reverse; /* アイテムが上に折り返す */
}
flex-wrap: wrap はレスポンシブなカードグリッドに不可欠です。これがないと、ビューポートがどれほど小さくなってもアイテムは縮小し続けます。
gap
gap は厳密にはフレックス専用プロパティではありません — CSSグリッドから来ています — しかしフレックスボックスでも動作し、本当に優れています。以前はmarginハックを使っていました。今は:
.container {
display: flex;
gap: 16px; /* 両方向に同じギャップ */
gap: 12px 24px; /* 行ギャップ 列ギャップ */
}
至る所で使います。marginより単純で、端にスペースを追加しません。
align-content
このプロパティは見逃しやすいです。align-content は justify-content のようなものですがクロス軸用で、複数行がある時(flex-wrap: wrap が有効でアイテムが実際に折り返した時)のみ効果があります。アイテムが1行に収まっている場合、align-content は見た目に影響しません。
.container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
align-content: center;
align-content: space-between;
}
これはおそらく最もよく誤解されるフレックスボックスプロパティです — アイテムが折り返していないため何も起きないのに、設定して変化を期待する人がいます。
アイテムレベルのプロパティ
コンテナではなくフレックスアイテム自身に設定するいくつかのプロパティがあります。
flex-grow — 利用可能なスペースを埋めるためにアイテムがどれだけ成長するか(デフォルト:0)
flex-shrink — スペースが不足した時にアイテムがどれだけ縮小するか(デフォルト:1)
flex-basis — 成長または縮小前のアイテムの開始サイズ(デフォルト:auto)
これら3つは flex ショートハンドでよく組み合わせます:
.item {
flex: 1; /* grow: 1, shrink: 1, basis: 0 — 等幅アイテム */
flex: 0 0 200px; /* 固定幅、成長も縮小もしない */
flex: 2; /* このアイテムはflex: 1の兄弟要素の2倍速く成長 */
}
align-self により、1つのアイテムがコンテナの align-items 設定を上書きできます:
.special-item {
align-self: flex-end; /* 兄弟要素がそうでなくても、このアイテムは下端に留まる */
}
一般的なパターン
何でも中央揃え(定番)
これはおそらく歴史上最もGoogleされたCSSスニペットです。divを水平・垂直両方で中央揃え:
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh; /* 縦方向に中央揃えするには何らかの高さが必要 */
}
たったこれだけです。2行(高さを数えると3行)。フレックスボックス以前、縦方向の中央揃えは本当に困難でした。今では体で覚えてしまっています。
レスポンシブナビゲーションバー
ロゴを左、ナビリンクを右に配置する水平ナビ:
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
モバイルでは列に切り替えることもできます:
@media (max-width: 768px) {
.navbar {
flex-direction: column;
gap: 12px;
}
}
レスポンシブカードグリッド
デスクトップでは横並び、モバイルでは縦積みになるカード:
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card {
flex: 1 1 300px; /* 成長、縮小、最小幅300px */
max-width: 400px;
}
flex: 1 1 300px がポイントです — 「幅300pxから始まり、必要に応じて成長・縮小する」という意味です。カードは1つもメディアクエリを書かなくても、小さな画面では自然と少ない列数に再配置されます。
スティッキーフッター
「コンテンツが少なくてもフッターが下端に留まる」定番パターン:
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; /* メインコンテンツが成長してフッターを下に押し出す */
}
footer {
/* 下端に留まる */
}
これはほぼすべてのプロジェクトで使っています。
フレックスボックス vs CSSグリッド:どちらを使うか
これについてオンラインで不必要な議論が多いです。正直な答えは:両方使え、用途が違う。
フレックスボックスを選ぶ時:
- アイテムの1行または1列がある
- アイテムが自然に折り返すことを望む(タグ、カードリスト)
- ナビゲーションバー、ツールバー、ボタングループを構築している
- 柔軟なアイテムサイズの1軸制御が必要
CSSグリッドを選ぶ時:
- 行と列の2次元レイアウトがある
- ヘッダー、サイドバー、メイン、フッターのあるページレベルのレイアウトを構築している
- アイテムを特定のセルに明示的に配置したい
- 複数列で一貫した行高が必要
実際には、1つのページでグリッドを全体レイアウトに、フレックスボックスをナビに、フレックスボックスをカードの内部レイアウトに、再びグリッドをデータテーブルに使うかもしれません。互いを補完します。
よくある間違いとハマりポイント
画像のflex-shrink: 0
デフォルトでは、フレックスアイテムは縮小できます。フレックスコンテナ内の画像は元のサイズより縮小し、見た目が悪くなります。修正:
img {
flex-shrink: 0;
}
またはショートハンドを使用:
img {
flex: 0 0 auto; /* 成長しない、縮小しない、自然サイズを使用 */
}
カードコンポーネントで潰れたアバター画像をデバッグしたことが何度もあります。
min-width: 0のオーバーフロー問題
これは微妙で人を狂わせます。デフォルトでは、フレックスアイテムは min-width: auto を持ち、コンテンツサイズ以下に縮小しません。長いテキストや幅広の要素を含むフレックスアイテムは、flex: 1 が設定されていてもコンテナからオーバーフローする場合があります。
修正:
.flex-item {
min-width: 0; /* コンテンツサイズ以下に縮小できるようにする */
overflow: hidden; /* またはスクロールが必要ならoverflow: auto */
}
これは特に、フレックスアイテム内でテキストを省略記号で切り詰める必要がある場合によく発生します。min-width: 0 がないとテキストは切り詰められず — 単にオーバーフローします。
align-contentは折り返しがある時だけ機能する
上述の通り、1行のフレックスコンテナに align-content を設定しても何も起きません。必要なのは:
- コンテナに
flex-wrap: wrap - 実際に複数行に折り返すのに十分なアイテム数
align-content を設定して変化がない場合は、アイテムが実際に折り返しているか確認してください。
margin: autoはフレックスコンテナで強力
これはハマりポイントというより秘密兵器ですが、人を驚かせます:フレックスアイテムに margin-left: auto を設定すると、それ(とその後のすべて)がコンテナの遠端に押し出されます。これにより、ラッパー要素なしで左にロゴ、右端にログインボタンのナビレイアウトが実現できます:
.nav {
display: flex;
align-items: center;
}
.nav-login {
margin-left: auto; /* ログインボタンを右端に押し出す */
}
レイアウトをビジュアルに構築
フレックスボックスのプロパティを読むのは有益ですが、メンタルモデルを本当に内面化する最速の方法は実際に試してみることです。CSSフレックスボックスジェネレーターでは、すべてのプロパティを切り替えてレイアウトがリアルタイムで更新されるのを確認できます。
10分間プロパティをクリックして試してみてください。ドキュメントを何時間も読むより速くメンタルモデルが固まります。
ブラウザサポート
フレックスボックスについて心配する必要がないこと:ブラウザサポートです。フレックスボックスは2015年頃から全ブラウザでサポートされています。すべてのモダンブラウザが完全にサポートしています。IE 11も部分的なサポートがありましたが、まだIE 11をサポートしているなら、もっと大きな問題があります。
ベンダープレフィックスやポリフィルなしで自信を持ってフレックスボックスを使えます。古い -webkit-flex と -ms-flexbox プレフィックスはとっくに引退しました。標準のフレックスボックスを書いてリリースするだけです。
まとめ
フレックスボックスが理解できたのは、「左や右に移動させる方法」ではなく、軸とアイテムの動作のシステムとして考えるようになった瞬間でした。メイン軸はアイテムが流れる方向です。クロス軸はそれに垂直です。justify-content はメイン軸を制御します。align-items はクロス軸を制御します。他のすべてはそこから流れます。
毎日使うパターン:
- 中央揃えに
display: flex; justify-content: center; align-items: center - ナビバーとツールバーに
justify-content: space-between - レスポンシブグリッドに
flex-wrap: wrapとgap - 等幅アイテムや成長するコンテンツエリアに
flex: 1 - スティッキーフッターに
flex-direction: column; min-height: 100vhとメインにflex: 1
画像の縮小問題、min-width: 0 のオーバーフロー問題、align-content には折り返したアイテムが必要という事実に注意してください。
フレックスボックスは、メンタルモデルが身についたら超能力を解放したような感覚になるCSSの機能の一つです。CSSグリッドの代わりにはなりません — 両方使いましょう — しかし1軸のレイアウトには最高です。