1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🎨 CSSを基礎から深く学ぼう【第二回】ボックスモデル・Flexbox・Grid・position・レスポンシブデザイン

1
Posted at

1. 👋 はじめに

前回はCSSの基礎・セレクター・詳細度・カスケード・CSS変数を学びました。今回は CSSレイアウトの核心 を解説します!

「CSSレイアウトが難しい」と感じる原因の多くは、ボックスモデルとFlexbox・Gridの仕組みを理解していないからです。
今回でその謎を完全に解き明かしましょう!

この記事を読めば:

  • ✅ ボックスモデルを理解できる
  • ✅ Flexboxで自在にレイアウトを組める
  • ✅ CSS Gridで複雑なレイアウトを作れる
  • ✅ positionプロパティを使いこなせる
  • ✅ レスポンシブデザインの実装方法がわかる

2. 📦 ボックスモデル

すべての要素は「箱」でできている

CSSでは、すべてのHTML要素は「箱(ボックス)」として扱われます。
この「箱」の構造を理解することがレイアウトの第一歩です。

box_model.jfif

部分 役割 例え
content テキストや画像などの中身 手紙の文章
padding コンテンツと枠線の間の余白 封筒の内側の余白
border 枠線 封筒の縁
margin 他の要素との間の余白 封筒同士の隙間

margin・padding の書き方

/* 上下左右すべて同じ値 */
margin: 16px;
padding: 16px;

/* 上下・左右を別々に指定 */
margin: 16px 8px;   /* 上下16px・左右8px */
padding: 8px 16px;  /* 上下8px・左右16px */

/* 上・右・下・左(時計回り)で別々に指定 */
margin: 8px 16px 4px 12px;

/* 個別に指定 */
margin-top: 16px;
margin-right: 8px;
margin-bottom: 16px;
margin-left: 8px;

padding-top: 8px;
padding-right: 16px;
padding-bottom: 8px;
padding-left: 16px;

box-sizing:ボックスの計算方法

box-sizing は「widthとheightが何を基準に計算されるか」を指定するプロパティです。

/* ❌ content-box(デフォルト):paddingとborderが幅に追加される */
.box {
  width: 200px;
  padding: 20px;
  border: 2px solid;
  /* 実際の表示幅:200 + 20×2 + 2×2 = 244px 😱 */
}

/* ✅ border-box:paddingとborderを含めた幅になる(現代の標準) */
.box {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 2px solid;
  /* 実際の表示幅:200px(指定通り!) */
}
/* 全要素にborder-boxを適用する(現代の標準的な設定) */
*,
*::before,
*::after {
  box-sizing: border-box;
}

💡 Tailwindなどのフレームワークは最初から border-box が設定されています。
素のCSSを書くときは必ずこのリセットを最初に書く習慣をつけましょう!

marginの相殺(マージンの折りたたみ)

/* ⚠️ 上下のmarginは相殺される! */
.box-a { margin-bottom: 32px; }
.box-b { margin-top: 16px; }

/* 実際の間隔は 32px + 16px = 48px ではなく
   大きい方の 32px になる(相殺)! */
【相殺が起きる条件】
  ✅ 上下方向のmarginが接している場合(左右は相殺されない)
  ✅ 親子要素のmarginが接している場合
  ❌ Flexbox・Gridのアイテムでは相殺は起きない

3. 🔧 Flexbox

Flexboxとは?

Flexboxは「子要素を1方向(横または縦)に並べるレイアウト方法」です。
ナビゲーション・カードの横並び・中央揃えなど、1方向のレイアウトに最適です。

Flexboxの基本

/* 親要素に display: flex を指定するだけで子要素が横並びになる */
.container {
  display: flex;
}

主軸と交差軸

Gemini_Generated_Image_dnj0bpdnj0bpdnj0.jfif

flex-direction:並ぶ方向

.container {
  flex-direction: row;         /* 横並び・左から右(デフォルト) */
  flex-direction: row-reverse; /* 横並び・右から左 */
  flex-direction: column;      /* 縦並び・上から下 */
  flex-direction: column-reverse; /* 縦並び・下から上 */
}

justify-content:主軸方向の揃え方

.container {
  justify-content: flex-start;    /* 左揃え(デフォルト) */
  justify-content: flex-end;      /* 右揃え */
  justify-content: center;        /* 中央揃え */
  justify-content: space-between; /* 両端に配置・均等間隔 */
  justify-content: space-around;  /* 均等間隔(両端にも余白) */
  justify-content: space-evenly;  /* すべての間隔が均等 */
}

Gemini_Generated_Image_g1cshsg1cshsg1cs.jfif

align-items:交差軸方向の揃え方

.container {
  align-items: stretch;    /* 高さを揃える(デフォルト) */
  align-items: flex-start; /* 上揃え */
  align-items: flex-end;   /* 下揃え */
  align-items: center;     /* 垂直中央揃え */
  align-items: baseline;   /* テキストのベースラインで揃える */
}

flex-wrap:折り返し

.container {
  flex-wrap: nowrap;  /* 折り返さない(デフォルト) */
  flex-wrap: wrap;    /* 幅が足りないとき折り返す */
  flex-wrap: wrap-reverse; /* 逆方向に折り返す */
}

gap:要素間の隙間

.container {
  gap: 16px;          /* 縦横すべて16px */
  gap: 16px 8px;      /* 行間16px・列間8px */
  row-gap: 16px;      /* 行間のみ */
  column-gap: 8px;    /* 列間のみ */
}

子要素に使うプロパティ

.item {
  /* flex-grow:余ったスペースをどれくらい取るか(比率) */
  flex-grow: 0;  /* デフォルト:余ったスペースを取らない */
  flex-grow: 1;  /* 余ったスペースを1の比率で取る */

  /* flex-shrink:スペースが足りないとき縮む比率 */
  flex-shrink: 1;  /* デフォルト:均等に縮む */
  flex-shrink: 0;  /* 縮まない */

  /* flex-basis:ベースとなる幅(または高さ) */
  flex-basis: auto;  /* デフォルト:コンテンツに応じる */
  flex-basis: 200px; /* 200pxをベースにする */

  /* flex:上3つのショートハンド */
  flex: 0 1 auto;   /* デフォルト値 */
  flex: 1;          /* flex-grow:1・flex-shrink:1・flex-basis:0% */
  flex: 0 0 200px;  /* 縮まない・200px固定 */
}

⚠️ flex: 1 の展開値に注意!
flex: 1 と書いたとき flex-basisauto ではなく 0% になります。

/* flex: 1; の実際の展開値 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;  /* auto ではなく 0% がポイント! */

flex-basis: 0% になることで、コンテンツの元々の幅を無視して
完全に均等な幅 でスペースを分配できます。
「なぜかアイテムの幅が均等にならない」というときは
flex-basis の値を確認してみましょう。

  /* order:表示順(小さい数が先に表示) */
  order: 0;   /* デフォルト */
  order: -1;  /* 先頭に移動 */
  order: 1;   /* 末尾に移動 */

  /* align-self:自分だけalign-itemsを上書き */
  align-self: center;
}

よくあるFlexboxのパターン

/* ① 水平・垂直の中央揃え(最も使われるパターン!) */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* ② ナビゲーションバー */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
}

/* ③ カードの横並び(折り返しあり) */
.card-list {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

/* ④ サイドバーレイアウト(サイドバー固定・メインが伸びる) */
.layout {
  display: flex;
  gap: 24px;
}
.sidebar { flex: 0 0 240px; }  /* 240px固定・縮まない */
.main { flex: 1; }              /* 残りのスペースをすべて使う */

4. 🔲 CSS Grid

CSS Gridとは?

CSS Gridは「行と列を組み合わせた2次元のレイアウト方法」です。
ダッシュボード・ギャラリー・複雑なページレイアウトに最適です。

Gridの基本

.container {
  display: grid;

  /* 列の定義 */
  grid-template-columns: 200px 1fr 1fr;
  /* → 1列目:200px固定・2列目と3列目:残りを均等に2分割 */

  grid-template-columns: repeat(3, 1fr);
  /* → 3列均等(1fr = 1fraction = 均等に分けた1つ分) */

  /* 行の定義 */
  grid-template-rows: 60px 1fr 60px;
  /* → ヘッダー:60px・メイン:残り全部・フッター:60px */

  /* 要素間の隙間 */
  gap: 16px;
  column-gap: 24px;  /* 列間のみ */
  row-gap: 16px;     /* 行間のみ */
}

fr(フラクション)とは?

fr = fraction(分数・割り合い)

grid-template-columns: 1fr 2fr 1fr の場合:

全体を 1+2+1 = 4 に分割
  1列目 → 全体の 1/4
  2列目 → 全体の 2/4(半分)
  3列目 → 全体の 1/4

┌───────┬──────────────┬───────┐
│  1fr  │     2fr      │  1fr  │
└───────┴──────────────┴───────┘

repeat():繰り返しの定義

/* repeat(繰り返し回数, 値) */
grid-template-columns: repeat(4, 1fr);
/* → 1fr 1fr 1fr 1fr と同じ(4列均等) */

/* auto-fill:コンテナの幅に応じて列数を自動調整 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* → 最小200px・最大1frのカラムを自動で並べる(レスポンシブグリッドに最適!) */

/* auto-fit:auto-fillと似ているが、空の列を折りたたむ */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

💡 auto-fillauto-fit の違い:アイテムが少ないときの挙動

コンテナの幅が800px・最小列幅200px(最大4列入る)の場合
アイテムが2つしかないとき:

auto-fill:
  [アイテム①] [アイテム②] [空の列] [空の列]
  → 空の列スペースを維持する

auto-fit:
  [   アイテム①   ] [   アイテム②   ]
  → 空の列を潰してアイテムが画面いっぱいに広がる
auto-fill auto-fit
空の列の扱い 維持する 潰す
少ないアイテム 左寄せになる 均等に広がる
向いている場面 後からアイテムが増える想定 アイテム数が少ない画面

子要素の配置

.item {
  /* grid-column:何列目から何列目まで占めるか */
  grid-column: 1 / 3;    /* 1列目から3列目の手前まで(2列分) */
  grid-column: 1 / -1;   /* 最初から最後まで(全列幅) */
  grid-column: span 2;   /* 2列分を占める */

  /* grid-row:何行目から何行目まで占めるか */
  grid-row: 1 / 3;       /* 1行目から3行目の手前まで(2行分) */
  grid-row: span 2;      /* 2行分を占める */
}

grid-template-areas:エリア名でレイアウトを定義

.container {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr 60px;
  grid-template-areas:
    "header  header"   /* 1行目:headerが2列全体 */
    "sidebar main"     /* 2行目:左にsidebar・右にmain */
    "footer  footer";  /* 3行目:footerが2列全体 */
  gap: 16px;
  min-height: 100vh;
}

/* 各要素にエリア名を割り当てる */
.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
<!-- HTMLはシンプルにそのまま -->
<div class="container">
  <header class="header">ヘッダー</header>
  <aside class="sidebar">サイドバー</aside>
  <main class="main">メインコンテンツ</main>
  <footer class="footer">フッター</footer>
</div>

FlexboxとGridの使い分け

Flexbox Grid
次元 1次元(横 or 縦) 2次元(横と縦)
向いている用途 ナビバー・カード横並び・中央揃え ダッシュボード・複雑なレイアウト
レイアウトの制御 子要素が自分のサイズを決める 親要素がレイアウトを決める
使い始めの難易度 低い 中程度
判断のコツ:

「1方向に並べたい」 → Flexbox
  例:横並びのナビメニュー・縦並びのリスト

「行と列で複雑に配置したい」 → Grid
  例:ECサイトの商品一覧・ダッシュボード

「どちらでも書ける」場合は →
  小さいコンポーネント内 → Flexbox
  ページ全体のレイアウト → Grid

5. 📍 position プロパティ

positionとは?

position プロパティは「要素の配置方法」を指定します。
toprightbottomleft プロパティと組み合わせて使います。

static(デフォルト)

.element {
  position: static; /* デフォルト:通常の文書の流れに従う */
  /* top・left などは効かない */
}

relative(相対配置)

.element {
  position: relative;
  top: 10px;   /* 本来の位置から10px下にずらす */
  left: 20px;  /* 本来の位置から20px右にずらす */
  /* ※ 元のスペースは保持される */
}
relativeのイメージ:

通常の位置:  [  A  ][  B  ][  C  ]
relative適用後:[  A  ][ B(↓10px・→20px) ][  C  ]
                        ↑ 元のスペースはそのまま

absolute(絶対配置)

/* 基準となる祖先要素(position: relative等)から相対的に配置 */
.parent {
  position: relative;  /* 基準点になる */
}

.child {
  position: absolute;
  top: 0;
  right: 0;
  /* 親要素の右上に配置される */
  /* ※ 文書の流れから外れる(他の要素に影響しない) */
}

⚠️ position: absolute の基準となる親要素に注意!
position: absoluteposition: static 以外の値(relativeabsolutefixedsticky)を持つ
最も近い祖先要素 を基準に配置されます。

親要素に position: relative を付け忘れると、
意図せず 画面全体(body)の右上まで飛んで行ってしまう という
初心者がよくハマるミスが起きます!

/* ❌ よくあるミス:親にpositionを指定し忘れる */
.parent { }  /* positionなし → static */
.badge {
  position: absolute;
  top: 0;
  right: 0;
  /* → 画面全体の右上に飛んでしまう! 😱 */
}

/* ✅ 正しい使い方:基準にしたい親に必ずrelativeをセット */
.parent { position: relative; }  /* ← これを忘れない! */
.badge {
  position: absolute;
  top: 0;
  right: 0;
  /* → .parentの右上に配置される ✅ */
}
absoluteのよくある使い方:

・バッジ(通知の数字)をアイコンの右上に表示
・ドロップダウンメニューを親要素の下に表示
・ツールチップ(ホバー時の説明)を要素の上に表示

.badge-wrapper {
  position: relative;  /* バッジの基準点 */
}
.badge {
  position: absolute;
  top: -8px;
  right: -8px;         /* 右上に表示 */
}

fixed(固定配置)

.element {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  /* ビューポート(画面)に対して固定 */
  /* スクロールしても動かない */
}
fixedのよくある使い方:
  ・固定ヘッダー(スクロールしても上部に固定)
  ・固定フッター(スクロールしても下部に固定)
  ・モーダルの背景オーバーレイ
  ・チャットの浮かせボタン

sticky(スクロール連動配置)

.element {
  position: sticky;
  top: 0;  /* スクロールして上端に来たら固定される */
  /* 通常は文書の流れに従い・指定位置に来たらfixedのように固定 */
}
stickyのよくある使い方:
  ・テーブルのヘッダー行(スクロールしても見出しを表示)
  ・セクションの見出し(目次のような挙動)
  ・サイドバーの追従

.table-header {
  position: sticky;
  top: 0;
  background: white;  /* 背景が透明だと下の内容が透けるので注意 */
  z-index: 10;
}

z-index:重なり順

/* z-indexが大きいほど手前に表示される */
.modal-overlay {
  position: fixed;
  z-index: 100;
}
.modal {
  position: fixed;
  z-index: 101;  /* overlayより手前 */
}
.tooltip {
  position: absolute;
  z-index: 200;
}

💡 z-indexはpositionがstatic以外の要素にしか効きません!
position: static(デフォルト)の要素に z-index を指定しても無視されます。


6. 📱 レスポンシブデザイン

レスポンシブデザインとは?

「画面サイズに応じてレイアウトが変わるデザイン」のことです。
スマホ・タブレット・PCすべてで見やすいページを1つのCSSで実現します。

メディアクエリの基本

/* min-width:この幅以上のとき適用(モバイルファースト) */
@media (min-width: 768px) {
  .container {
    flex-direction: row;
  }
}

/* max-width:この幅以下のとき適用(デスクトップファースト) */
@media (max-width: 767px) {
  .container {
    flex-direction: column;
  }
}

/* 範囲指定 */
@media (min-width: 768px) and (max-width: 1023px) {
  /* タブレットのみ */
}

💡 モダンな書き方(Media Queries Level 4)
現代のブラウザでは比較演算子を使った直感的な記法が使えます!

/* 従来の書き方 */
@media (min-width: 768px) { ... }
@media (max-width: 767px) { ... }

/* モダンな書き方(直感的で読みやすい!) */
@media (width >= 768px) { ... }   /* 768px以上 */
@media (width <= 767px) { ... }   /* 767px以下 */
@media (768px <= width <= 1023px) { ... }  /* 範囲指定もスッキリ! */

Chrome・Firefox・Safari など主要ブラウザで広くサポートされています。

モバイルファーストで書こう

/* ✅ モバイルファースト(推奨):スマホ向けをデフォルトに */

/* デフォルト:スマホ向け */
.card-list {
  display: flex;
  flex-direction: column;  /* 縦並び */
  gap: 16px;
}

/* タブレット以上(768px〜) */
@media (min-width: 768px) {
  .card-list {
    flex-direction: row;   /* 横並びに変更 */
    flex-wrap: wrap;
  }
}

/* PC以上(1024px〜) */
@media (min-width: 1024px) {
  .card-list {
    gap: 24px;
  }
}

よく使うブレークポイント

名前 対象デバイス
sm 640px〜 大きめのスマホ
md 768px〜 タブレット
lg 1024px〜 小さめのPC
xl 1280px〜 普通のPC
2xl 1536px〜 大きなモニター

💡 これはTailwind CSSのブレークポイントと同じです!
フレームワークを使う場合もこの値が基準になることが多いです。

レスポンシブ対応のパターン集

/* ① レスポンシブなカードグリッド(Gridを使う) */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  /* ブレークポイントを書かなくてもカード幅が自動調整される! */
}

/* ② フォントサイズをビューポートに応じて変える */
h1 {
  font-size: clamp(24px, 5vw, 48px);
  /* clamp(最小値, 推奨値, 最大値) */
  /* → 最小24px・ビューポート幅の5%・最大48px */
}

/* ③ 画像をレスポンシブにする */
img {
  max-width: 100%;  /* 親要素の幅を超えない */
  height: auto;     /* 縦横比を保つ */
}

/* ④ コンテナの幅を制限して中央に配置 */
.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;    /* 左右中央揃え */
  padding: 0 16px;   /* 小さい画面での左右余白 */
}

画面の向き・印刷対応

/* 横向き(landscape)のとき */
@media (orientation: landscape) {
  .hero {
    min-height: 50vh;
  }
}

/* 印刷時のスタイル */
@media print {
  .no-print {
    display: none;  /* 印刷時に非表示 */
  }
  body {
    font-size: 12pt;
    color: black;
  }
}

7. 🎯 まとめ

概念 一言で言うと
📦 ボックスモデル すべての要素はcontent・padding・border・marginの「箱」
box-sizing: border-box paddingとborderを含めた幅で計算する(現代の標準)
🔧 Flexbox 1方向(横 or 縦)に要素を並べるレイアウト方法
🔲 Grid 行と列の2次元でレイアウトを作る方法
📍 position 要素の配置方法(static・relative・absolute・fixed・sticky)
📱 レスポンシブ メディアクエリで画面サイズに応じてスタイルを変える

レイアウト選択の早見表

要素を横 or 縦に並べたい    → Flexbox
行と列で複雑に配置したい    → Grid
要素を画面に固定したい      → position: fixed
親要素の右上にバッジを表示  → position: absolute
スクロールで追従させたい    → position: sticky

「CSSレイアウトはパズルではなく仕組み」です。
ボックスモデル・Flexbox・Gridの仕組みを理解すれば、
どんなレイアウトも「なぜこう書くのか」を理解しながら実装できます💪

次回は アニメーション・疑似クラス・高度なCSS を解説します!
transition・animation・最新CSS機能を学びましょう🌟

💬 質問や感想があれば、コメント欄でお気軽にどうぞ!
👍 役に立ったら、いいね&ストックをお願いします!
🎓 ここまで読んでくださって、本当にありがとうございました!


🔗 シリーズ記事

  • 【第一回】CSSの基礎・セレクター・詳細度・カスケード・CSS変数
  • 【第二回】ボックスモデル・Flexbox・Grid・position・レスポンシブ(この記事)
  • 【第三回】アニメーション・疑似クラス・高度なCSS(近日公開)
  • 【第四回】Tailwind CSS・shadcn/ui・CSSフレームワーク完全解説(近日公開)
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?