【CSS】レスポンシブデザイン対応の基本:メディアクエリの書き方とパーツ別サンプル集

css-responsive

あらゆる画面サイズでWebサイトを整えて表示させるレスポンシブデザインは、Web制作において欠かせないスキルです。

本記事では、メディアクエリの基礎やレイアウト崩れの解決策、実務で使える汎用UIパーツのテンプレートを解説します。

また、CSSに関するカテゴリーページから学びたい内容を決めたい人は、以下のCSSページをご確認ください。

目次

レスポンシブデザインとは?CSSの基本とメディアクエリ

Web制作において、PC・タブレット・スマートフォンなど、どの端末から見てもレイアウトが崩れず表示される仕組みをレスポンシブデザインと呼びます。

かつてはPC用とスマホ用で全く別のHTMLページを用意する時代もありましたが、現在は1つのHTMLに対して「画面幅に応じてCSSの適用ルールを変える」というレスポンシブ対応が世界標準です。

ここでは、レスポンシブデザインの作り方を解説します。

レスポンシブデザインとは?CSSの基本とメディアクエリ
  • メディアクエリとブレイクポイントの設定
  • CSSファイルは分けるべき?フレームワークの活用

メディアクエリとブレイクポイントの設定

レスポンシブデザインを実現するCSSの機能が「メディアクエリ(@media)」です。

そして、レイアウトを切り替える画面幅の境界線のことを「ブレイクポイント」と呼びます。

ブレイクポイントの書き方は、@media (max-width: 〇〇px) { ... }のように記述し、「画面幅が〇〇px以下の時だけ、CSSを適用する」という指示を出します。

レスポンシブのスマホサイズとしては、近年は768px(一般的なタブレットの縦向き以下)を境界線にするのが主流です。

メディアクエリを書く際は、max-width(PCベースで書き、スマホで上書きする)か、min-width(スマホベースで書き、PCで上書きする)のどちらか一方に統一してください。

これらを1つのファイル内で無秩序に混在させると、どのCSSが優先されているのか分からなくなり、後から修正不可能なスパゲティコードが完成してしまいます。

PCサイズ(横並び) ⇔ スマホサイズ(縦並び)

メインコンテンツ
サイドバー
/* 💡 ベースのスタイル(PC用・横並び) */
.layout-box {
  display: flex;
  gap: 20px;
}

/* 💡 メディアクエリ(画面幅768px以下の場合に適用) */
@media (max-width: 768px) {
  .layout-box {
    flex-direction: column; /* 💡 横並びを縦並びに上書き */
  }
}
HTMLコード表示
<div class="resp-sec1-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="resp-toggle-btn" onclick="document.getElementById('resp-demo1').classList.toggle('is-mobile')">
      📱 スマホ表示に切り替え
    </button>
  </div>

  <p class="resp-caption">PCサイズ(横並び) ⇔ スマホサイズ(縦並び)</p>
  
  <div id="resp-demo1" class="resp-layout-box">
    <div class="resp-item">メインコンテンツ</div>
    <div class="resp-item resp-sidebar">サイドバー</div>
  </div>

  <div class="resp-code">
    /* 💡 ベースのスタイル(PC用・横並び) */<br>
    <span class="hl-blue">.layout-box</span> {<br>
      <span class="hl-green">display: flex;</span><br>
      <span class="hl-green">gap: 20px;</span><br>
    }<br><br>

    /* 💡 メディアクエリ(画面幅768px以下の場合に適用) */<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.layout-box</span> {<br>
        <span class="hl-red">flex-direction: column;</span> /* 💡 横並びを縦並びに上書き */<br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.resp-sec1-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}
.resp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
}

.resp-toggle-btn {
  background-color: #0d6efd;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  font-weight: bold;
  cursor: pointer;
  transition: 0.2s;
}
.resp-toggle-btn:hover { background-color: #0b5ed7; }

/* PCベースのレイアウト */
.resp-layout-box {
  display: flex;
  gap: 15px;
  transition: all 0.3s ease;
  background-color: #e9ecef;
  padding: 15px;
  border-radius: 8px;
}

.resp-item {
  flex: 2;
  background-color: #198754;
  color: #fff;
  padding: 30px;
  text-align: center;
  font-weight: bold;
  border-radius: 4px;
}
.resp-sidebar {
  flex: 1;
  background-color: #6c757d;
}

/* 💡 JSで付与する擬似的なスマホクラス(メディアクエリの代わり) */
.resp-layout-box.is-mobile {
  flex-direction: column; /* 縦並びになる */
}

.resp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  margin-top: 20px;
  border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }

min-widthmax-widthの使い方を詳しく知りたい人は「【html&css】min-widthとmax-widthの使い方【レスポンシブ対応】」を一読ください。

CSSファイルは分けるべき?フレームワークの活用

レスポンシブデザインを学び始めると、「PC用のstyle-pc.cssとスマホ用のstyle-sp.cssのように、レスポンシブcssに分けるべきか?」という疑問にぶつかります。

ファイルを分けたほうが整理されているように見えますが、実務では最悪のアンチパターンです。

ボタンの色を1つ変更する際、PC用とスマホ用の両方のファイルを開いて修正しなければならず、「スマホ側だけ変更を忘れる」というバグを引き起こします。

また、読み込むファイル数が増えることでサイトの表示速度(パフォーマンス)も低下します。

CSSファイルは1つにまとめ、「対象となるパーツのスタイルのすぐ真下」にメディアクエリを書くのがよいです。

また、CSSフレームワークを使用する場合、自分でメディアクエリを書かなくてもクラス名を付与するだけでレスポンシブ対応が完了します。

なお、wordpressでレスポンシブを扱う際、SWELLなどの高機能テーマではブレイクポイントが計算されたクラスが用意されていますが、追加でカスタマイズCSSを書く際も該当パーツのすぐ下に@mediaを書くルールを徹底してください。

⭕️ メンテナンス性の高い実務レベルのCSS構造

/* ❌ ファイルの最後にまとめてスマホ用を書く */
/* どこに何の設定があるか探しに行くのが大変 */
.header { width: 1000px; }
.card { display: flex; }

@media (max-width: 768px) {
  .header { width: 100%; }
  .card { display: block; }
}

/* ⭕️ パーツごとにメディアクエリをまとめる */
/* — ヘッダーパーツ — */
.header {
  width: 1000px;
}
@media (max-width: 768px) {
  .header {
    width: 100%;
  }
}

/* — カードパーツ — */
.card {
  display: flex;
}
@media (max-width: 768px) {
  .card {
    flex-direction: column;
  }
}
HTMLコード表示
<div class="resp-sec2-wrapper">
  
  <p class="resp-caption">⭕️ メンテナンス性の高い実務レベルのCSS構造</p>

  <div class="resp-code">
    /* ❌ ファイルの最後にまとめてスマホ用を書く */<br>
    <span class="hl-comment">/* どこに何の設定があるか探しに行くのが大変 */</span><br>
    <span class="hl-blue">.header</span> { <span class="hl-green">width: 1000px;</span> }<br>
    <span class="hl-blue">.card</span> { <span class="hl-green">display: flex;</span> }<br>
    <br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.header</span> { <span class="hl-green">width: 100%;</span> }<br>
      <span class="hl-blue">.card</span> { <span class="hl-green">display: block;</span> }<br>
    }<br><br>

    /* ⭕️ パーツごとにメディアクエリをまとめる */<br>
    <span class="hl-comment">/* --- ヘッダーパーツ --- */</span><br>
    <span class="hl-blue">.header</span> {<br>
      <span class="hl-green">width: 1000px;</span><br>
    }<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.header</span> {<br>
        <span class="hl-red">width: 100%;</span><br>
      }<br>
    }<br><br>

    <span class="hl-comment">/* --- カードパーツ --- */</span><br>
    <span class="hl-blue">.card</span> {<br>
      <span class="hl-green">display: flex;</span><br>
    }<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.card</span> {<br>
        <span class="hl-red">flex-direction: column;</span><br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.resp-sec2-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}
.hl-comment { color: #6c757d; font-style: italic; }

CSSをどこに書くべきか詳しく知りたい人は「CSSの優先順位はどう決まる?どこに書くかと外部CSSの読み込み&インラインの記述」を一読ください。

テキストとレイアウトのレスポンシブ化

レスポンシブデザインの基本である「メディアクエリ」を理解したら、次は具体的な中身の調整に入ります。

PCとスマホでは画面の横幅が異なるため、テキストの大きさや改行位置、要素の並び順(レイアウト)を柔軟に変化させる必要があります。

ここでは、Web制作で標準となっている可変なテキスト指定、FlexboxやGridを使ったレイアウトの組み替え、高さと幅の指定方法を解説します。

テキストとレイアウトのレスポンシブ化
  • フォントサイズを画面幅に合わせて可変にする
  • スマホとPCでの改行のコントロールと文字幅
  • Flexbox/Gridによる横並びから縦並びへの変更
  • 幅と高さの自動調整

フォントサイズを画面幅に合わせて可変にする

スマホで見た時に文字が大きすぎて読みにくい、逆にPCで見た時に文字が小さすぎてスカスカという問題は、文字サイズの設定が甘いことが原因です。

かつてはメディアクエリを使って、PCなら24px、タブレットなら20px、スマホなら16px…と細かく指定していましたが、現代のフォントサイズは進化しています。

文字サイズにおけるレスポンシブの最適解は、clamp()関数を使用することです。

font-size: clamp(最小サイズ, 推奨サイズ(vw), 最大サイズ);と記述することで、「基本は画面幅に合わせて可変するが、16pxよりは小さくならず、24pxよりは大きくならない」という文字サイズのコントロールが1行で完結します。

また、固定値を持たせる場合はアクセシビリティを尊重するため、pxではなくrem指定を使用するのがよいです。

❌ px指定(スマホでもデカいままではみ出す)

絶対に文字サイズが変わらない見出し

⭕️ clamp()指定(スマホ幅に合わせて美しく縮む)

画面幅に合わせて可変するスマートな見出し

/* ❌ 固定値のためスマホでレイアウトが崩れる */
.wrong-text {
  font-size: 32px;
}

/* ⭕️ 最小16px、可変5vw、最大32pxの範囲で自動調整 */
.correct-text {
  font-size: clamp(1rem, 5vw, 2rem); /* 💡 メディアクエリ不要の魔法 */
}
HTMLコード表示
<div class="rsp-txt-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-txt-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅(375px相当)に切り替え
    </button>
  </div>

  <div id="rsp-txt-demo" class="rsp-txt-container">
    <p class="rsp-caption">❌ px指定(スマホでもデカいままではみ出す)</p>
    <p class="rsp-txt-wrong">絶対に文字サイズが変わらない見出し</p>

    <p class="rsp-caption" style="margin-top: 30px;">⭕️ clamp()指定(スマホ幅に合わせて美しく縮む)</p>
    <p class="rsp-txt-correct">画面幅に合わせて可変するスマートな見出し</p>
  </div>

  <div class="rsp-code">
    /* ❌ 固定値のためスマホでレイアウトが崩れる */<br>
    <span class="hl-blue">.wrong-text</span> {<br>
      <span class="hl-red">font-size: 32px;</span><br>
    }<br><br>

    /* ⭕️ 最小16px、可変5vw、最大32pxの範囲で自動調整 */<br>
    <span class="hl-blue">.correct-text</span> {<br>
      <span class="hl-red">font-size: clamp(1rem, 5vw, 2rem);</span> /* 💡 メディアクエリ不要の魔法 */<br>
    }
  </div>

</div>
CSSコード表示
.rsp-txt-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}
.rsp-caption { font-size: 12px; font-weight: bold; color: #666; margin: 0 0 5px 0; }

.rsp-toggle-btn {
  background-color: #0d6efd; color: white; border: none; padding: 10px 20px;
  border-radius: 5px; font-weight: bold; cursor: pointer; transition: 0.2s;
}

/* デモ用コンテナ(PC幅のシミュレート) */
.rsp-txt-container {
  background-color: #fff;
  padding: 20px;
  border: 2px dashed #ccc;
  width: 100%;
  transition: width 0.3s ease;
  overflow: hidden; /* はみ出し確認用 */
  white-space: nowrap;
}

/* スマホ幅のシミュレート */
.rsp-txt-container.is-mobile {
  width: 375px; /* スマホの一般的な幅 */
  margin: 0 auto;
}

.rsp-txt-wrong {
  font-size: 32px; /* ❌ 固定 */
  font-weight: bold; margin: 0; color: #dc3545;
}

.rsp-txt-correct {
  /* ⭕️ 16px ~ 5vw ~ 32px の間で可変(※デモ用にvwの代わりにコンテナ幅の%に依存するcqiを使用していますが、実務ではvwでOKです) */
  font-size: clamp(16px, 5cqi, 32px); 
  font-weight: bold; margin: 0; color: #198754;
}

/* コンテナクエリ(デモの可変再現用) */
.rsp-txt-container { container-type: inline-size; }

.rsp-code { background-color: #282c34; color: #abb2bf; padding: 15px; border-radius: 4px; font-family: monospace; font-size: 13px; line-height: 1.6; margin-top: 20px; }
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }

フォントサイズの調整を詳しく知りたい人は「【HTML】フォントサイズ(文字)の指定:px・rem・em・%の変更と自動調整」を一読ください。

スマホとPCでの改行のコントロールと文字幅

デザインカンプ(完成図)を忠実に再現しようとするあまり、改行のトラブルを引き起こすコーダーは後を絶ちません。

PCでは綺麗に見えるように<br>タグを入れても、画面幅の狭いスマホで見ると変な位置で文字が改行されてしまうという現象が起きます。

これを防ぐためには、改行させない、あるいは特定の幅でのみ改行させるというコントロールが必要です。

PCでのみ改行したい場合は、改行タグにクラスを付け(例:<br class="pc-only">)、スマホのメディアクエリ内でdisplay: none;を指定して改行を無効化します。

また、単語の途中で不自然に改行されるのを防ぐには、テキストを囲むブロックにoverflow-wrap: anywhere;word-break: auto-phrase;を指定してブラウザに改行を任せるのがよいです。

❌ brタグ放置(スマホで変な改行になる)

レスポンシブデザインでは、
画面幅に応じた対応が必須です。

⭕️ pc-onlyクラス付与(スマホではbrが消え、自然に折り返す)

レスポンシブデザインでは、
画面幅に応じた対応が必須です。

/* 💡 HTML:
と記述しておく */

/* ⭕️ スマホ幅(768px以下)の時に改行を消す */
@media (max-width: 768px) {
  .pc-only {
    display: none; /* 💡 brタグを非表示にして無効化 */
  }
}
HTMLコード表示
<div class="rsp-br-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-br-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅(300px相当)に切り替え
    </button>
  </div>

  <div id="rsp-br-demo" class="rsp-br-container">
    <p class="rsp-caption">❌ brタグ放置(スマホで変な改行になる)</p>
    <p class="rsp-br-wrong">
      レスポンシブデザインでは、<br>
      画面幅に応じた対応が必須です。
    </p>

    <p class="rsp-caption" style="margin-top: 20px;">⭕️ pc-onlyクラス付与(スマホではbrが消え、自然に折り返す)</p>
    <p class="rsp-br-correct">
      レスポンシブデザインでは、<br class="pc-only-br">
      画面幅に応じた対応が必須です。
    </p>
  </div>

  <div class="rsp-code">
    /* 💡 HTML: <br class="pc-only"> と記述しておく */<br><br>
    
    /* ⭕️ スマホ幅(768px以下)の時に改行を消す */<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.pc-only</span> {<br>
        <span class="hl-red">display: none;</span> /* 💡 brタグを非表示にして無効化 */<br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.rsp-br-wrapper { background-color: #f8f9fa; padding: 20px; border-radius: 8px; border: 1px solid #dee2e6; }
.rsp-br-container { background-color: #fff; padding: 20px; border: 2px dashed #ccc; width: 100%; transition: width 0.3s ease; }

/* スマホシミュレート */
.rsp-br-container.is-mobile { width: 300px; margin: 0 auto; }

.rsp-br-wrong { background-color: #f8d7da; padding: 10px; border-radius: 4px; }
.rsp-br-correct { background-color: #d1e7dd; padding: 10px; border-radius: 4px; }

/* スマホ表示の時に pc-only-br を非表示にする */
.rsp-br-container.is-mobile .pc-only-br {
  display: none;
}

brタグの使い方を詳しく知りたい人は「【HTML】brタグ(改行)の使い方:pタグとの違いや効かない時の対策」を一読ください。

Flexbox/Gridによる横並びから縦並びへの変更

2列や段組みを組む際、PCでは横並びに配置し、画面の狭いスマホでは縦並びに変更するのがよくあるレイアウトパターンです。

これを実現するには、flexレスポンシブやグリッドレイアウトレスポンシブの技術を使います。

現代の横並び→縦並びの切り替えはFlexbox(display: flex;)のflex-directionを変更するのが簡単かつ確実です。

PC用にdisplay: flex;(デフォルトで横並びのrow)を指定しておき、スマホのメディアクエリ内でflex-direction: column;に上書きするだけで、一瞬で縦並びへと変化します。

Card 1
Card 2
Card 3
/* 💡 PC用(ベース):Flexboxで横並びに */
.card-container {
  display: flex;
  gap: 20px;
}

/* 💡 スマホ用:方向を縦に変更するだけ */
@media (max-width: 768px) {
  .card-container {
    flex-direction: column; /* 💡 魔法の1行(縦並び) */
  }
}
HTMLコード表示
<div class="rsp-flex-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-flex-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅に切り替え
    </button>
  </div>

  <div id="rsp-flex-demo" class="rsp-flex-container">
    <div class="rsp-flex-item">Card 1</div>
    <div class="rsp-flex-item">Card 2</div>
    <div class="rsp-flex-item">Card 3</div>
  </div>

  <div class="rsp-code">
    /* 💡 PC用(ベース):Flexboxで横並びに */<br>
    <span class="hl-blue">.card-container</span> {<br>
      <span class="hl-red">display: flex;</span><br>
      <span class="hl-green">gap: 20px;</span><br>
    }<br><br>

    /* 💡 スマホ用:方向を縦に変更するだけ */<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.card-container</span> {<br>
        <span class="hl-red">flex-direction: column;</span> /* 💡 魔法の1行(縦並び) */<br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.rsp-flex-wrapper { background-color: #f8f9fa; padding: 20px; border-radius: 8px; border: 1px solid #dee2e6; }

/* PCベース:横並び */
.rsp-flex-container {
  display: flex;
  gap: 15px;
  transition: all 0.3s ease;
  background-color: #e9ecef;
  padding: 15px;
  border-radius: 8px;
}

.rsp-flex-item {
  flex: 1;
  background-color: #0d6efd;
  color: white;
  padding: 30px 0;
  text-align: center;
  font-weight: bold;
  border-radius: 4px;
}

/* スマホシミュレート:縦並び */
.rsp-flex-container.is-mobile {
  flex-direction: column; /* 💡 縦並びに変更 */
  width: 300px;
  margin: 0 auto;
}

Flexboxの使い方を詳しく知りたい人は「【CSS】flexの使い方:justify-content・align-items・gap」を一読ください。

また、Gridの使い方を詳しく知りたい人は「【CSS】Gridの使い方:Flexboxとの違いやレスポンシブ」を一読ください。

幅と高さの自動調整

レスポンシブデザインする際、厄介なのが幅と高さの指定です。

レスポンシブデザインにおいて、幅にはmax-width(最大幅)、高さにはmin-height(最小の高さ)を使用するのがよいです。


  • width: 100%; max-width: 1000px;と指定することで、「基本は画面いっぱいに広がるが、1000px以上には大きくならない」という安全な箱が作れます。
  • 高さ
    heightではなくmin-heightを使えば、文字が増えたら勝手に高さが伸びてくれます。
  • 高さを揃える
    横に並んだ要素の高さを揃えたい場合は、固定のheightを使うのではなく、親要素にdisplay: flex;を指定するだけで、子要素の高さは一番高いものに揃います。

❌ height: 120px; (固定)

文章が長くなりスマホ幅で折り返すと、箱の高さが固定されているため、このようにボックスの枠を突き破って無惨に文字が外へはみ出してしまいます。

⭕️ min-height: 120px; (可変)

文章が長くなり折り返しても、最小の高さを指定しているだけなので、中のコンテンツ量に合わせてボックスの高さが自動的に下へ伸びて包み込んでくれます。

/* ❌ 初心者のミス:高さを固定してしまう */
.wrong-box {
  height: 120px; /* 💡 どんなに文字が増えても箱は大きくならない */
}

/* ⭕️ プロの鉄則:最小の高さを指定して、あとは可変にする */
.correct-box {
  min-height: 120px; /* 💡 基本は120pxだが、中身が増えれば勝手に伸びる */
}
HTMLコード表示
<div class="rsp-size-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-size-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅(文字が折り返して行数が増える)
    </button>
  </div>

  <div id="rsp-size-demo" class="rsp-size-container">
    
    <div class="rsp-box-wrong">
      <p class="rsp-caption" style="color:#dc3545;">❌ height: 120px; (固定)</p>
      <p class="rsp-text">文章が長くなりスマホ幅で折り返すと、箱の高さが固定されているため、このようにボックスの枠を突き破って無惨に文字が外へはみ出してしまいます。</p>
    </div>

    <div class="rsp-box-correct">
      <p class="rsp-caption" style="color:#198754;">⭕️ min-height: 120px; (可変)</p>
      <p class="rsp-text">文章が長くなり折り返しても、最小の高さを指定しているだけなので、中のコンテンツ量に合わせてボックスの高さが自動的に下へ伸びて包み込んでくれます。</p>
    </div>

  </div>

  <div class="rsp-code">
    /* ❌ 高さを固定してしまう */<br>
    <span class="hl-blue">.wrong-box</span> {<br>
      <span class="hl-red">height: 120px;</span> /* 💡 どんなに文字が増えても箱は大きくならない */<br>
    }<br><br>

    /* ⭕️ 最小の高さを指定して、あとは可変にする */<br>
    <span class="hl-blue">.correct-box</span> {<br>
      <span class="hl-red">min-height: 120px;</span> /* 💡 基本は120pxだが、中身が増えれば勝手に伸びる */<br>
    }
  </div>

</div>
CSSコード表示
.rsp-size-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rsp-size-container {
  display: flex;
  gap: 20px;
  background-color: #e9ecef;
  padding: 20px;
  /* 💡 飛び出した文字が見切れないように、下部に大きな余白を設ける */
  padding-bottom: 60px; 
  border-radius: 8px;
  transition: all 0.3s ease;
  /* 高さを中身に合わせる設定 */
  align-items: flex-start; 
}

/* スマホシミュレート */
.rsp-size-container.is-mobile {
  width: 280px; /* 確実に文字を折り返させるために狭くする */
  margin: 0 auto;
  flex-direction: column;
  gap: 60px; /* 縦並びの時に、飛び出した文字が下の箱に被らないよう間隔を空ける */
}

/* 共通のテキストスタイル */
.rsp-caption {
  font-weight: bold;
  font-size: 14px;
  margin: 0 0 8px 0;
}
.rsp-text {
  font-size: 14px;
  line-height: 1.6;
  margin: 0;
  color: #333; /* 💡 飛び出しても読めるように濃いグレーにする */
}

/* ❌ 失敗例(絶対に伸びないように強制する) */
.rsp-box-wrong {
  flex: 1;
  padding: 15px;
  background-color: #f8d7da;
  border: 2px solid #dc3545; /* 枠線を付けて「箱の限界」を強調する */
  border-radius: 4px;
  height: 120px !important; 
  max-height: 120px !important;
  /* 💡 はみ出た部分を隠さず、必ず外に飛び出させる */
  overflow: visible !important; 
}

/* ⭕️ 成功例(中身に合わせて伸びる) */
.rsp-box-correct {
  flex: 1;
  padding: 15px;
  background-color: #d1e7dd;
  border: 2px solid #198754;
  border-radius: 4px;
  /* 💡 最小の高さを設定(文字が増えれば伸びる) */
  min-height: 120px !important; 
}

.rsp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  margin-top: 20px;
  border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }

widthheightの設定を詳しく知りたい人は「【html&css】width(横幅)とheight(高さ)の指定とボックスモデル」を一読ください。

画像と動画のレスポンシブ対応

Webサイトをスマホ対応させる際、テキストやレイアウトと同じくらい厄介なのが「メディア(画像・動画)」の扱いです。

スマホの小さな画面にPC用の画像を表示させると画面からはみ出したり、縮小しようとして縦横の比率がおかしくなってしまうトラブルが頻発します。

ここでは、CSSを活用した「崩れない、重くならない」最適なメディアのレスポンシブ手法を解説します。

画像と動画のレスポンシブ対応
  • 画像の縮小と縦横比の維持
  • PCとスマホで画像を切り替える
  • YouTubeや背景動画の埋め込みをレスポンシブにする
  • 正方形や正円のレイアウトを崩さずに可変させる

画像の縮小と縦横比の維持

画像の基本は、画面幅に合わせて画像を自動的に縮小させることです。

比率を変えずに縮小を実現するには、画像(img)に対してmax-width: 100%; height: auto;を指定することです。

これだけで本来の比率を保ったまま縮小されます。

実務では、カード型レイアウトのサムネイルなどで「どんなサイズの画像がアップロードされても、指定した比率(例:16:9)で切り抜く」という要件が必須です。

この場合は、最新プロパティであるaspect-ratioobject-fit: cover;を組み合わせるのがよいです。

❌ heightを固定(PCは横伸び、スマホは縦潰れ)

歪んだ画像

⭕️ aspect-ratio + object-fit(常に綺麗に切り抜く)

綺麗な画像
/* ❌ 高さを固定してしまう */
.img-wrong {
  width: 100%;
  height: 250px; /* 💡 画面幅が変わっても高さが固定のため激しく歪む */
}

/* ⭕️ 比率を指定してカバーする */
.img-correct {
  width: 100%;
  aspect-ratio: 16 / 9; /* 💡 常に16:9の比率を維持する */
  object-fit: cover; /* 💡 歪ませず、はみ出た部分を綺麗に切り取る */
}
HTMLコード表示
<div class="rsp-img-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-img-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅に切り替え
    </button>
  </div>

  <div id="rsp-img-demo" class="rsp-img-container">
    <div class="rsp-img-box">
      <p class="rsp-caption">❌ heightを固定(PCは横伸び、スマホは縦潰れ)</p>
      <img src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?auto=format&fit=crop&w=800&q=80" class="img-wrong" alt="歪んだ画像">
    </div>
    
    <div class="rsp-img-box">
      <p class="rsp-caption" style="color:#198754;">⭕️ aspect-ratio + object-fit(常に綺麗に切り抜く)</p>
      <img src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?auto=format&fit=crop&w=800&q=80" class="img-correct" alt="綺麗な画像">
    </div>
  </div>

  <div class="rsp-code">
    /* ❌ 高さを固定してしまう */<br>
    <span class="hl-blue">.img-wrong</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-red">height: 250px;</span> /* 💡 画面幅が変わっても高さが固定のため激しく歪む */<br>
    }<br><br>

    /* ⭕️ 比率を指定してカバーする */<br>
    <span class="hl-blue">.img-correct</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-red">aspect-ratio: 16 / 9;</span> /* 💡 常に16:9の比率を維持する */<br>
      <span class="hl-red">object-fit: cover;</span> /* 💡 歪ませず、はみ出た部分を綺麗に切り取る */<br>
    }
  </div>

</div>
CSSコード表示
.rsp-img-wrapper { background-color: #f8f9fa; padding: 20px; border-radius: 8px; border: 1px solid #dee2e6; }
.rsp-img-container { display: flex; gap: 20px; transition: width 0.3s ease; }
.rsp-img-container.is-mobile { width: 280px; margin: 0 auto; flex-direction: column; }
.rsp-img-box { flex: 1; }
.rsp-caption { font-weight: bold; font-size: 13px; margin: 0 0 5px 0; color: #dc3545; }

/* ❌ 失敗例 */
.img-wrong {
  width: 100% !important;
  /* 💡 高さを少し高めに固定することで、スマホの狭い幅になった時に縦長の正方形になり、強烈に潰れるようにする */
  height: 250px !important; 
  object-fit: fill !important; 
  border-radius: 8px;
  display: block;
}

/* ⭕️ 成功例 */
.img-correct {
  width: 100% !important;
  height: auto !important;
  aspect-ratio: 16 / 9 !important; /* 💡 16:9比率を完璧に維持 */
  object-fit: cover !important;    /* 💡 歪ませずにトリミング */
  border-radius: 8px;
  display: block;
}

.rsp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  margin-top: 20px;
  border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }

imgタグの使い方を詳しく知りたい人は「【HTML】imgタグの使い方:src・altの使い分けや画像リサイズ・中央寄せ」を一読ください。

PCとスマホで画像を切り替える

メインビジュアル(ヒーロー画像)などで、PCでは横長の画像、スマホでは縦長の画像を出し分けたい場面はよくあります。

HTMLの<img>を切り替える場合は、CSSではなくHTMLの<picture><source>タグを使うのがよいです。

一方、CSSで背景画像の切り替えを行う場合は、メディアクエリでbackground-imageを上書きします。

この際、常に画面を覆う背景画像にするため、background-size: cover;background-position: center;を併用してください。

HERO IMAGE
/* 💡 ベースの設定(画面いっぱいにカバーする) */
.hero-section {
  background-size: cover; /* 💡 隙間なく画面を覆う */
  background-position: center;
  background-image: url(‘pc-image.jpg’); /* PC用の横長画像 */
}

/* 💡 スマホ用:背景画像のURLだけを上書きする */
@media (max-width: 768px) {
  .hero-section {
    background-image: url(‘sp-image.jpg’); /* 💡 スマホ用の縦長画像に切り替え */
  }
}
HTMLコード表示
<div class="rsp-bg-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-bg-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅に切り替え(画像が変わります)
    </button>
  </div>

  <div id="rsp-bg-demo" class="rsp-bg-hero">
    <div style="margin:0; text-shadow: 0 2px 6px rgba(0,0,0,0.8); font-size: 24px;">HERO IMAGE</div>
  </div>

  <div class="rsp-code">
    /* 💡 ベースの設定(画面いっぱいにカバーする) */<br>
    <span class="hl-blue">.hero-section</span> {<br>
      <span class="hl-green">background-size: cover;</span> /* 💡 隙間なく画面を覆う */<br>
      <span class="hl-green">background-position: center;</span><br>
      <span class="hl-red">background-image: url('pc-image.jpg');</span> /* PC用の横長画像 */<br>
    }<br><br>

    /* 💡 スマホ用:背景画像のURLだけを上書きする */<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.hero-section</span> {<br>
        <span class="hl-red">background-image: url('sp-image.jpg');</span> /* 💡 スマホ用の縦長画像に切り替え */<br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.rsp-bg-wrapper { 
  background-color: #f8f9fa; 
  padding: 20px; 
  border-radius: 8px; 
  border: 1px solid #dee2e6; 
}

/* PCベース:横長画像 */
.rsp-bg-hero {
  width: 100%;
  height: 250px; /* PCでは横長の比率になる高さ */
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  transition: all 0.4s ease;
  
  /* 💡 万が一画像が読み込めなかった時のための保険(暗いグレー) */
  background-color: #6c757d !important;
  
  /* 💡 カバーと中央配置の鉄則 */
  background-size: cover !important;
  background-position: center !important;
  /* 安定して表示されるダミー画像(自然の風景) */
  background-image: url('https://picsum.photos/id/1018/1000/500') !important;
}

/* スマホシミュレート:縦長画像に切り替え */
.rsp-bg-hero.is-mobile {
  width: 300px;
  height: 400px; /* スマホらしく縦長の比率に変更 */
  margin: 0 auto;
  /* 💡 スマホ用の画像(別の風景)で上書き */
  background-image: url('https://picsum.photos/id/1015/400/800') !important;
}

.rsp-toggle-btn { background-color: #0d6efd; color: white; border: none; padding: 10px 20px; border-radius: 5px; font-weight: bold; cursor: pointer; transition: 0.2s; }
.rsp-toggle-btn:hover { background-color: #0b5ed7; }
.rsp-code { background-color: #282c34; color: #abb2bf; padding: 15px; border-radius: 4px; font-family: monospace; font-size: 13px; line-height: 1.6; margin-top: 20px; border-left: 4px solid #0d6efd; }
.hl-blue { color: #61afef; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }

pictureタグの使い方を詳しく知りたい人は「【HTML】pictureタグの使い方:imgとの違い・レスポンシブ対応」を一読ください。

また、background-imageプロパティの使い方を詳しく知りたい人は「【CSS】background-imageの使い方:サイズ・透過・レスポンシブ」を一読ください。

YouTubeや背景動画の埋め込みをレスポンシブにする

Webサイトに動画を埋め込む際、レスポンシブの知識がないとレイアウトが崩れます。

特に、youtubeの埋め込みに関するレスポンシブは初心者がつまづくポイントです。

YouTubeのiframeや動画タグ(video)に対して、width: 100%; height: auto;aspect-ratio: 16 / 9;を指定するだけでPCでもスマホでも比率を保ったまま可変します。

背景動画として使う場合は、画像と同じくobject-fit: cover;を動画タグに付与すれば画面いっぱいに広がります。

❌ width:100%のみ(高さが固定され黒帯ができる)

⭕️ aspect-ratio: 16/9(比率を完璧に維持)

/* ❌ 横幅だけ100%にする */
.yt-wrong {
  width: 100%;
  /* heightの指定がないため、HTMLタグに直書きされた height=”315″ が維持されてしまう */
}

/* ⭕️ 高さをautoでリセットし、アスペクト比を強制する */
.yt-correct {
  width: 100%;
  height: auto; /* 💡 直書きの height=”315″ を無効化する(必須) */
  aspect-ratio: 16 / 9; /* 💡 YouTubeの標準比率である16:9を強制 */
}
HTMLコード表示
<div class="rsp-yt-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-yt-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅に切り替え(黒帯の発生を比較)
    </button>
  </div>

  <div id="rsp-yt-demo" class="rsp-yt-container">
    <div class="rsp-yt-box">
      <p class="rsp-caption">❌ width:100%のみ(高さが固定され黒帯ができる)</p>
      <iframe class="yt-wrong" width="560" height="315" src="https://www.youtube.com/embed/LXb3EKWsInQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
    </div>
    
    <div class="rsp-yt-box">
      <p class="rsp-caption" style="color:#198754;">⭕️ aspect-ratio: 16/9(比率を完璧に維持)</p>
      <iframe class="yt-correct" width="560" height="315" src="https://www.youtube.com/embed/LXb3EKWsInQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
    </div>
  </div>

  <div class="rsp-code">
    /* ❌ 横幅だけ100%にする */<br>
    <span class="hl-blue">.yt-wrong</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-comment">/* heightの指定がないため、HTMLタグに直書きされた height="315" が維持されてしまう */</span><br>
    }<br><br>

    /* ⭕️ 高さをautoでリセットし、アスペクト比を強制する */<br>
    <span class="hl-blue">.yt-correct</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-red">height: auto;</span> /* 💡 直書きの height="315" を無効化する(必須) */<br>
      <span class="hl-red">aspect-ratio: 16 / 9;</span> /* 💡 YouTubeの標準比率である16:9を強制 */<br>
    }
  </div>

</div>
CSSコード表示
.rsp-yt-wrapper { background-color: #f8f9fa; padding: 20px; border-radius: 8px; border: 1px solid #dee2e6; }
.rsp-yt-container { display: flex; gap: 20px; transition: width 0.3s ease; }
.rsp-yt-container.is-mobile { width: 300px; margin: 0 auto; flex-direction: column; }
.rsp-yt-box { flex: 1; }

/* ❌ 失敗例 */
.yt-wrong {
  width: 100% !important;
  max-width: 100% !important;
  border-radius: 8px;
  background-color: #000;
}

/* ⭕️ 成功例 */
.yt-correct {
  width: 100% !important;
  max-width: 100% !important;
  /* 💡 HTMLのheight="315"を打ち消す */
  height: auto !important; 
  /* 💡 完璧な比率を維持 */
  aspect-ratio: 16 / 9 !important; 
  border-radius: 8px;
  background-color: #000;
}

.rsp-toggle-btn { background-color: #0d6efd; color: white; border: none; padding: 10px 20px; border-radius: 5px; font-weight: bold; cursor: pointer; transition: 0.2s; }
.rsp-toggle-btn:hover { background-color: #0b5ed7; }
.rsp-code { background-color: #282c34; color: #abb2bf; padding: 15px; border-radius: 4px; font-family: monospace; font-size: 13px; line-height: 1.6; margin-top: 20px; border-left: 4px solid #0d6efd; }
.rsp-caption { font-weight: bold; font-size: 13px; margin: 0 0 8px 0; color: #dc3545; }
.hl-blue { color: #61afef; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

正方形や正円のレイアウトを崩さずに可変させる

スタッフ紹介のアバター画像やInstagram風のグリッドレイアウトを作る際、正方形や正円をどう実装するかでコーダーの腕が試されます。

これもaspect-ratioプロパティの登場によって一撃で解決できるようになりました。

要素に対してaspect-ratio: 1 / 1;(縦横比 1:1)を指定するだけで、横幅が伸び縮みしても高さが計算されて正方形を保ちます。

これを正円(丸)にしたい場合は、これに加えてborder-radius: 50%;を指定するだけで完成します。

正方形
1:1
正円
1:1
正方形
1:1
/* 💡 レスポンシブな正方形 */
.square-box {
  width: 100%; /* 横幅は親に合わせて可変 */
  height: auto;
  aspect-ratio: 1 / 1; /* 💡 常に縦横比1:1(正方形)をキープ */
}

/* 💡 レスポンシブな正円(丸) */
.circle-box {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1; /* 1:1の正方形を作ってから… */
  border-radius: 50%; /* 💡 角を削って丸にする */
}
HTMLコード表示
<div class="rsp-shape-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-shape-demo').classList.toggle('is-mobile')">
      📱 コンテナ幅を縮小する
    </button>
  </div>

  <div id="rsp-shape-demo" class="rsp-shape-container">
    <div class="shape-square">正方形<br>1:1</div>
    <div class="shape-circle">正円<br>1:1</div>
    <div class="shape-square">正方形<br>1:1</div>
  </div>

  <div class="rsp-code">
    /* 💡 レスポンシブな正方形 */<br>
    <span class="hl-blue">.square-box</span> {<br>
      <span class="hl-green">width: 100%;</span> /* 横幅は親に合わせて可変 */<br>
      <span class="hl-green">height: auto;</span><br>
      <span class="hl-red">aspect-ratio: 1 / 1;</span> /* 💡 常に縦横比1:1(正方形)をキープ */<br>
    }<br><br>

    /* 💡 レスポンシブな正円(丸) */<br>
    <span class="hl-blue">.circle-box</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-green">height: auto;</span><br>
      <span class="hl-red">aspect-ratio: 1 / 1;</span> /* 1:1の正方形を作ってから... */<br>
      <span class="hl-red">border-radius: 50%;</span> /* 💡 角を削って丸にする */<br>
    }
  </div>

</div>
CSSコード表示
.rsp-shape-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rsp-shape-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  width: 100%;
  transition: width 0.3s ease;
}

/* 縮小シミュレート */
.rsp-shape-container.is-mobile {
  width: 50%; /* 幅を半分に縮小 */
  margin: 0 auto;
}

/* ⭕️ レスポンシブ正方形 */
.shape-square {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  background-color: #0d6efd;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  text-align: center;
  border-radius: 8px;
}

/* ⭕️ レスポンシブ正円 */
.shape-circle {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1; /* 💡 正方形を作ってから */
  border-radius: 50%;  /* 💡 丸くする */
  background-color: #198754;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  text-align: center;
}

borderプロパティの使い方を詳しく知りたい人は「【CSS】borderの使い方:線の種類・角丸・重なりの解決策」を一読ください。

コピペで使える!UIパーツ別レスポンシブ実装・テンプレート

Webサイトのスマホ対応において、ゼロからすべてを構築するのは手間がかかります。

実務の現場では、汎用性の高いレスポンシブ テンプレートを用意しておき、プロジェクトごとにカスタマイズして使うのが一般的です。

ここでは、実務の案件に導入できる「レスポンシブ対応テンプレート」をパーツ別にご紹介します。

シンプルでスタイリッシュなデザインをベースにしているため、既存のWordPressテーマ等のスタイルを邪魔せずに組み込めるサンプルとしてご活用ください。

UIパーツ別レスポンシブ実装・テンプレート
  • ハンバーガーメニュー・ドロップダウン・タブの作成
  • テーブル(表)とフォームをスマホでスクロールさせる
  • ギャラリー・スライダー・フロー・吹き出しの実装

ハンバーガーメニュー・ドロップダウン・タブの作成

スマホ対応の代表格とも言えるのがハンバーガーメニューです。

PC画面では横に並んだ横並びメニューバーやホバーで多階層が開くドロップダウンメニューを採用し、スマホ画面では三本線のハンバーガー メニューへ切り替えるのがよくあるパターンです。

また、限られたスマホの画面領域を有効活用するため、タブ切り替えも使用されます。

メニューやタブといったナビゲーションUIを構築する際は、aタグに対してdisplay: block;を指定し、余白を広くとって指でタップしやすい領域を確保してください。

また、ハンバーガーメニューの開閉は、JavaScriptでbodyやラッパー要素に.is-activeクラスを付与し、CSS側で表示・非表示を切り替えるのがよいです。

/* 💡 ベース(PC用):メニューを横並びにする */
.nav-list {
  display: flex;
  gap: 20px;
}
.nav-hamburger {
  display: none; /* 💡 PCではハンバーガーボタンを隠す */
}

/* 💡 スマホ用:ハンバーガーメニュー化 */
@media (max-width: 768px) {
  .nav-hamburger {
    display: block; /* ボタンを表示 */
  }
  .nav-menu {
    position: absolute; /* 画面を覆うように配置 */
    display: none; /* 💡 初期状態は非表示 */
  }
  /* 💡 ボタンが押され、親に .is-open が付いた時だけ表示 */
  .is-open .nav-menu {
    display: block;
  }
}
HTMLコード表示
<div class="rsp-nav-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-nav-demo').classList.toggle('is-mobile')">
      📱 スマホ表示(ハンバーガー化)に切り替え
    </button>
  </div>

  <div id="rsp-nav-demo" class="rsp-nav-container">
    <header class="nav-header">
      <div class="nav-logo">LOGO</div>
      
      <button class="nav-hamburger" onclick="this.parentElement.classList.toggle('is-open')">
        <span></span><span></span><span></span>
      </button>

      <nav class="nav-menu">
        <ul class="nav-list">
          <li><a href="#">Home</a></li>
          <li><a href="#">About</a></li>
          <li><a href="#">Service</a></li>
          <li><a href="#">Contact</a></li>
        </ul>
      </nav>
    </header>
  </div>

  <div class="rsp-code">
    /* 💡 ベース(PC用):メニューを横並びにする */<br>
    <span class="hl-blue">.nav-list</span> {<br>
      <span class="hl-green">display: flex;</span><br>
      <span class="hl-green">gap: 20px;</span><br>
    }<br>
    <span class="hl-blue">.nav-hamburger</span> {<br>
      <span class="hl-red">display: none;</span> /* 💡 PCではハンバーガーボタンを隠す */<br>
    }<br><br>

    /* 💡 スマホ用:ハンバーガーメニュー化 */<br>
    <span class="hl-blue">@media</span> (<span class="hl-green">max-width: 768px</span>) {<br>
      <span class="hl-blue">.nav-hamburger</span> {<br>
        <span class="hl-red">display: block;</span> /* ボタンを表示 */<br>
      }<br>
      <span class="hl-blue">.nav-menu</span> {<br>
        <span class="hl-red">position: absolute;</span> /* 画面を覆うように配置 */<br>
        <span class="hl-red">display: none;</span> /* 💡 初期状態は非表示 */<br>
      }<br>
      <span class="hl-comment">/* 💡 ボタンが押され、親に .is-open が付いた時だけ表示 */</span><br>
      <span class="hl-blue">.is-open .nav-menu</span> {<br>
        <span class="hl-red">display: block;</span><br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.rsp-nav-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rsp-toggle-btn {
  background-color: #0d6efd;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  font-weight: bold;
  cursor: pointer;
  transition: 0.2s;
}

.rsp-toggle-btn:hover {
  background-color: #0b5ed7;
}

.rsp-nav-container {
  background-color: #e9ecef;
  border-radius: 8px;
  overflow: hidden;
  transition: width 0.3s ease;
  position: relative;
  height: 300px;
}

.rsp-nav-container.is-mobile {
  width: 320px;
  margin: 0 auto;
}

/* ヘッダー全体 */
.nav-header {
  background-color: #333;
  color: #fff;
  padding: 15px 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative;
}

.nav-logo {
  font-weight: bold;
  font-size: 20px;
  letter-spacing: 2px;
}

/* PCメニューリスト */
.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 20px;
}

.nav-list a {
  color: #fff;
  text-decoration: none;
  font-size: 14px;
  padding: 10px;
  display: block;
  transition: 0.2s;
}

.nav-list a:hover {
  color: #0d6efd;
}

/* ハンバーガーボタン(初期非表示) */
.nav-hamburger {
  display: none;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 5px;
  width: 30px;
  height: 24px;
  position: relative;
  z-index: 100;
}

.nav-hamburger span {
  display: block;
  width: 100%;
  height: 2px;
  background-color: #fff;
  position: absolute;
  left: 0;
  transition: 0.3s;
}

.nav-hamburger span:nth-child(1) {
  top: 0;
}

.nav-hamburger span:nth-child(2) {
  top: 50%;
  transform: translateY(-50%);
}

.nav-hamburger span:nth-child(3) {
  bottom: 0;
}

/* --- スマホ時のスタイル --- */
.rsp-nav-container.is-mobile .nav-hamburger {
  display: block;
}

.rsp-nav-container.is-mobile .nav-menu {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  background-color: #222;
  /* 💡 通常は非表示 */
  display: none; 
  z-index: 90;
}

.rsp-nav-container.is-mobile .nav-list {
  flex-direction: column;
  gap: 0;
}

.rsp-nav-container.is-mobile .nav-list a {
  padding: 15px 20px;
  border-bottom: 1px solid #444;
}

/* 💡 開いた状態(JSで is-open が付与された時) */
.rsp-nav-container.is-mobile .is-open .nav-menu {
  display: block;
}

.rsp-nav-container.is-mobile .is-open .nav-hamburger span:nth-child(1) {
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
}

.rsp-nav-container.is-mobile .is-open .nav-hamburger span:nth-child(2) {
  opacity: 0;
}

.rsp-nav-container.is-mobile .is-open .nav-hamburger span:nth-child(3) {
  bottom: auto;
  top: 50%;
  transform: translateY(-50%) rotate(-45deg);
}

.rsp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  margin-top: 20px;
  border-left: 4px solid #0d6efd;
}

.hl-blue {
  color: #61afef;
  font-weight: bold;
}

.hl-green {
  color: #98c379;
  font-weight: bold;
}

.hl-red {
  color: #e06c75;
  font-weight: bold;
}

.hl-comment {
  color: #6c757d;
  font-style: italic;
}

ドロップダウンメニューの作り方を詳しく知りたい人は「【HTML】プルダウン・セレクトボックス・ドロップダウンの作り方:コンボボックスとの違い」を一読ください。

テーブル(表)とフォームをスマホでスクロールさせる

テーブル表やお問い合わせフォームは、画面からはみ出しやすく、レイアウト崩れしやすいパーツです。

列が多いテーブルは、無理に縮めようとせず「外側をdivで囲み、横スクロールさせる(overflow-x: auto;)」のがよいです。

同時に、表内のテキストにはwhite-space: nowrap;(自動改行させない)を指定することで、表のレイアウトを維持できます。

フォームに関しては、スマホ時は項目名と入力欄を横並びから縦並びに変更し、入力欄のfont-size16px以上に設定してください。

スワイプ(スクロール)で隠れた部分を確認できます

プラン名 初期費用 月額料金 サポート体制 データ容量
ライト 無料 1,980円 メールのみ 10GB
スタンダード 5,000円 4,980円 チャット対応 100GB
/* 💡 テーブルを囲む親要素にスクロールを指定する */
.table-scroll-box {
  width: 100%;
  overflow-x: auto; /* 💡 はみ出た部分は横スクロールさせる */
  -webkit-overflow-scrolling: touch; /* iOSでの滑らかなスクロール */
}

/* 💡 テーブル内の文字が勝手に改行されるのを防ぐ */
.responsive-table th, .responsive-table td {
  white-space: nowrap; /* 💡 意図しない縦長化を防ぐ */
}
HTMLコード表示
<div class="rsp-table-wrapper">
  
  <div style="text-align: center; margin-bottom: 15px;">
    <button class="rsp-toggle-btn" onclick="document.getElementById('rsp-table-demo').classList.toggle('is-mobile')">
      📱 スマホ表示幅(横スクロール発生)に切り替え
    </button>
  </div>

  <div id="rsp-table-demo" class="rsp-table-container">
    <p class="rsp-caption">スワイプ(スクロール)で隠れた部分を確認できます</p>
    
    <div class="table-scroll-box">
      <table class="responsive-table">
        <tr>
          <th>プラン名</th>
          <th>初期費用</th>
          <th>月額料金</th>
          <th>サポート体制</th>
          <th>データ容量</th>
        </tr>
        <tr>
          <td>ライト</td>
          <td>無料</td>
          <td>1,980円</td>
          <td>メールのみ</td>
          <td>10GB</td>
        </tr>
        <tr>
          <td>スタンダード</td>
          <td>5,000円</td>
          <td>4,980円</td>
          <td>チャット対応</td>
          <td>100GB</td>
        </tr>
      </table>
    </div>
  </div>

  <div class="rsp-code">
    /* 💡 テーブルを囲む親要素にスクロールを指定する */<br>
    <span class="hl-blue">.table-scroll-box</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-red">overflow-x: auto;</span> /* 💡 はみ出た部分は横スクロールさせる */<br>
      <span class="hl-green">-webkit-overflow-scrolling: touch;</span> /* iOSでの滑らかなスクロール */<br>
    }<br><br>

    /* 💡 テーブル内の文字が勝手に改行されるのを防ぐ */<br>
    <span class="hl-blue">.responsive-table th, .responsive-table td</span> {<br>
      <span class="hl-red">white-space: nowrap;</span> /* 💡 意図しない縦長化を防ぐ */<br>
    }
  </div>

</div>
CSSコード表示
.rsp-table-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rsp-table-container {
  transition: width 0.3s ease;
  width: 100%;
  background-color: #e9ecef;
  padding: 20px;
  border-radius: 8px;
}

/* スマホ幅をシミュレート */
.rsp-table-container.is-mobile {
  width: 320px;
  margin: 0 auto;
}

.rsp-caption {
  font-weight: bold;
  font-size: 13px;
  margin: 0 0 10px 0;
  color: #198754;
  text-align: center;
}

/* 💡 スクロールさせる親要素 */
.table-scroll-box {
  width: 100%;
  overflow-x: auto;
  /* スクロールバーのスタイル */
  scrollbar-width: thin;
  scrollbar-color: #adb5bd #e9ecef;
}

.table-scroll-box::-webkit-scrollbar {
  height: 8px;
}

.table-scroll-box::-webkit-scrollbar-thumb {
  background: #adb5bd;
  border-radius: 4px;
}

/* テーブルの基本デザイン */
.responsive-table {
  width: 100%;
  border-collapse: collapse;
  background-color: #fff;
  font-size: 14px;
}

.responsive-table th, .responsive-table td {
  border: 1px solid #dee2e6;
  padding: 12px 15px;
  /* 💡 狭くなっても無理に改行させない */
  white-space: nowrap; 
}

.responsive-table th {
  background-color: #0d6efd;
  color: white;
  font-weight: bold;
  text-align: left;
}

.responsive-table tr:nth-child(even) {
  background-color: #f8f9fa;
}

tableタグの使い方あるいはテーブルの作り方を詳しく知りたい人は「【HTML】tableタグ(テーブル)の使い方:枠線・セル結合・レスポンシブ」を一読ください。

まとめ

分かりやすいようにまとめを記載します。

本記事のまとめ
  • スマホでのレイアウト適用には、HTML側の<meta name="viewport">指定が必須である。
  • メディアクエリの記述はmax-widthまたはmin-widthのどちらか一方のルールに統一する。
  • CSSファイルはデバイスごとに分割せず、対象となるパーツの直下にメディアクエリを記述する。
  • フォントサイズは固定値(px)や単一のvwを避け、clamp()関数を使って可変させる。
  • PC用の改行(<br>)は専用クラスを付与し、スマホ表示時にdisplay: none;で無効化する。
  • 横並びから縦並びへの変更は、Flexboxのflex-direction: column;で制御する。
  • 要素が画面からはみ出すのを防ぐため、widthheightの固定を避け、max-widthmin-heightを使用する。
  • 画像の比率崩れを防ぐにはmax-width: 100%; height: auto;を基本とし、必要に応じてaspect-ratioobject-fitを併用する。
  • YouTubeなどの埋め込みiframeは、高さをautoにした上でaspect-ratio: 16 / 9;で比率を維持する。
  • 列の多いテーブル(表)は無理に縮小せず、親要素にoverflow-x: auto;を指定して横スクロールさせる。
  • タイル状のレイアウトは、Gridのrepeat(auto-fit, minmax(...))を使えばメディアクエリ不要で実装できる。

よくある質問(FAQ)

スマホで確認するとCSSが効かない・表示が変わらないのはなぜですか?

最も多い原因は、HTMLの<head>内にviewport(ビューポート)のメタタグが記述されていないことです。

<meta name="viewport" content="width=device-width, initial-scale=1.0">という一行を記述しないと、スマホはPC用の画面を縮小して表示しようとするため、CSSで設定した画面幅の条件が正しく認識されません。

レスポンシブ対応を始める前の必須準備です。

ブレイクポイントは、何pxに設定するのが正解ですか?

厳密な正解(全デバイス共通の数値)はありませんが、実務では「768px」を一つの大きな境界線とするのが標準的です。

@media (max-width: 768px) { ... }と記述し、768px以下の時にスマホ用のレイアウトに上書きするというアプローチをとれば、ほぼすべてのスマートフォンで表示されます。

スマホで見ると画像が画面からはみ出したり、歪んだりしてしまいます。

画像(imgタグ)に対して、CSSでmax-width: 100%; height: auto;を指定してください。

初心者はwidth: 300px;のように固定値で指定してしまいがちですが、max-width: 100%;にすることで「本来のサイズ以上には大きくならないが、画面が狭くなったら合わせて縮む」という画像になります。

height: auto;を併用することで縦横比も崩れません。

PC用とスマホ用でCSSファイルは分けた方がいいですか?

いいえ、1つのファイルにまとめるのがよいです。

デバイスごとにファイルを分けてしまうと、「PC側は色を変えたのに、スマホ側の変更を忘れた」といった修正漏れのバグが多発し、メンテナンス性が低下します。

1つのファイルの中で「.button { ... }のすぐ下に@media(...) { .button { ... } }を書く」というように、パーツごとにPCとスマホの記述をセットにしてまとめるのがよいです。

画面幅に合わせて文字サイズを自動で可変させるには?

clamp()関数を使うのが簡単かつ確実です。

font-size: clamp(16px, 5vw, 24px);のように指定すると、「基本は画面幅に合わせて伸び縮みするが、最小16pxよりは小さくならず、最大24pxよりは大きくならない」という設定が1行で完結します。

以前のように、メディアクエリで文字サイズを刻んで指定する必要はなくなりました。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次