9/7まで 最大30%OFF 初心者編|無料コーディング教材|HTML・CSS・jQueryを実践で学ぶ

HTMLをレスポンシブ対応する方法|viewport・メディアクエリを初心者向けに解説

同じWebページがPC、タブレット、スマートフォンへ適応するイメージ

PCではきれいに表示できたのに、スマートフォンで見ると文字が小さくなったり、横スクロールが出たりして困っていませんか?画面幅の違いを考えずに固定サイズで作ると、狭い画面でレイアウトが崩れやすくなります。

HTMLをレスポンシブ対応するには、viewportを設定し、要素の幅を柔軟にして、必要な場所だけメディアクエリで配置を切り替えます。この記事では、変更前のコードからスマホ対応を完成させるまで、初心者向けに順番に解説します。

レスポンシブ対応とは画面幅に合わせて表示を調整すること

レスポンシブWebデザインは、同じHTMLを使いながら、画面の広さや利用環境に合わせて読みやすいレイアウトへ変える考え方です。PC、タブレット、スマートフォンごとに別ページを作るという意味ではありません。

広い画面ではカードや本文とサイドバーを横に並べ、狭い画面では縦に並べます。画像や文章も親要素の幅に収め、横方向にはみ出さないようにします。

viewport、柔軟な幅、メディアクエリでレスポンシブ対応する流れ
レスポンシブ対応はviewport、柔軟な幅、メディアクエリを組み合わせます

基本は図の3点です。viewportで端末幅を正しく扱い、相対的な幅と最大幅で内容を柔軟にし、配置が窮屈になる箇所だけ@mediaで切り替えます。

変更前の固定幅ページを確認する

まずは、レスポンシブ対応前の例を見てみましょう。次のHTMLには3枚のカードがあり、CSSではコンテンツ全体を960px、各カードを300pxに固定しています。

<!doctype html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>レスポンシブ対応の練習</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="site-header">
    <h1>Sample Site</h1>
  </header>

  <main class="container">
    <h2>おすすめ記事</h2>
    <div class="card-list">
      <article class="card">
        <img src="images/html.jpg" alt="HTMLのコード画面">
        <h3>HTML入門</h3>
        <p>HTMLの基本的な書き方を学びます。</p>
      </article>
      <article class="card">
        <img src="images/css.jpg" alt="CSSのコード画面">
        <h3>CSS入門</h3>
        <p>CSSで見た目を整える方法を学びます。</p>
      </article>
      <article class="card">
        <img src="images/layout.jpg" alt="Webページのレイアウト図">
        <h3>レイアウト入門</h3>
        <p>要素を並べる方法を学びます。</p>
      </article>
    </div>
  </main>
</body>
</html>
body {
  margin: 0;
  font-family: sans-serif;
}

.site-header,
.container {
  width: 960px;
  margin-inline: auto;
}

.card-list {
  display: flex;
  gap: 30px;
}

.card {
  width: 300px;
}

.card img {
  width: 300px;
}

幅が960px未満の画面でもコンテンツは縮まらないため、右側が画面外へはみ出します。画像とカードも固定幅なので、スマートフォンでは横スクロールが必要です。

headにviewportを設定する

最初に、head要素へviewportのmetaタグを追加します。スマートフォンの表示領域を端末の画面幅に合わせるための基本設定です。

<meta name="viewport" content="width=device-width, initial-scale=1">

width=device-widthは表示領域の幅を端末幅へ合わせ、initial-scale=1は最初の表示倍率を等倍にします。HTMLファイルのhead内へ1回だけ書きます。

user-scalable=nomaximum-scale=1で拡大を禁止すると、文字を拡大したい人が利用しにくくなります。特別な理由がなければズームを制限しないでください。

固定幅を柔軟な幅へ変更する

次に、960pxと300pxの固定幅を見直します。親要素は画面より広くならないようにし、画像はカード幅に合わせて縮小します。

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  color: #1f2937;
  background: #f5f7fb;
  font-family: system-ui, -apple-system, sans-serif;
  line-height: 1.7;
}

.site-header,
.container {
  width: min(100% - 32px, 960px);
  margin-inline: auto;
}

img {
  max-width: 100%;
  height: auto;
}

.card {
  min-width: 0;
  padding: 20px;
  border-radius: 12px;
  background: #ffffff;
}

width: min(100% - 32px, 960px)は、通常は画面幅から左右16pxずつを引いた幅を使い、広い画面でも最大960pxまでにします。固定された最大幅と、狭い画面に収まる柔軟な幅を両立できます。

画像のmax-width: 100%は、元画像が親要素より大きいときに縮小します。height: autoを併用すると、縦横比を保ったまま表示できます。

モバイルファーストでカードを並べる

狭い画面向けの1列を基本にし、十分な幅がある場合だけ列数を増やします。このように小さい画面から設計する方法をモバイルファーストと呼びます。

.card-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
}

@media (min-width: 600px) {
  .card-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 900px) {
  .card-list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

画面が600px未満では1列、600px以上では2列、900px以上では3列です。min-widthを使うため、基本のCSSから広い画面向けの指定を段階的に追加しています。

minmax(0, 1fr)は各列を同じ割合にし、長い文字列が入っても列が必要以上に広がりにくくする指定です。カードの内容が増えても、利用できる幅を均等に分けられます。

メディアクエリの基本構文

メディアクエリは、表示領域の幅などが条件に合う場合だけCSSを適用する仕組みです。よく使うのはmin-widthmax-widthです。

/* 768px以上で適用 */
@media (min-width: 768px) {
  .example {
    display: grid;
  }
}

/* 767px以下で適用 */
@media (max-width: 767px) {
  .example {
    display: block;
  }
}

min-widthは指定幅以上、max-widthは指定幅以下で適用されます。同じ箇所で両方を混在させると条件を追いにくくなるため、モバイルファーストならmin-widthを中心にそろえると理解しやすくなります。

ブレークポイントは内容が崩れる幅で決める

レイアウトを切り替える幅をブレークポイントと呼びます。「スマホは375px、タブレットは768px」と端末名だけで固定するのではなく、実際の内容が窮屈になる位置で決めます。

ブラウザ幅を広い状態から少しずつ狭め、カードの文字が不自然に折り返す、メニューがはみ出す、本文が細くなりすぎる場所を探してください。その少し手前で列数や配置を切り替えます。

ブレークポイントを細かく増やしすぎると、後からCSSを直すのが難しくなります。最初は1〜2個から始め、内容に必要な場合だけ追加しましょう。

横並びをスマホで縦並びにする

本文とサイドバーの2カラムも、狭い画面では縦並びにします。基本は1列にし、十分な幅があるときだけ2列へ変更します。

.page-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

@media (min-width: 768px) {
  .page-layout {
    grid-template-columns: minmax(0, 1fr) minmax(240px, 300px);
  }
}

HTMLでは重要なmainを先に、補足のasideを後に書いておきます。1列になったときも、本文を読んだあとにサイドバーが続く自然な順番になります。

画像・動画・表のはみ出しを防ぐ

レイアウトを1列にしても、画像や動画、表が固定幅のままだと横スクロールが残ります。コンテンツの種類ごとに対策します。

img,
video {
  max-width: 100%;
  height: auto;
}

.video-wrapper {
  aspect-ratio: 16 / 9;
}

.video-wrapper iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.table-wrapper {
  overflow-x: auto;
}

動画のiframeは、縦横比を持つ親要素で囲むと画面幅に合わせて縮められます。列の多い表は無理に縮小すると読めなくなるため、表を囲む要素だけ横スクロールできるようにします。

ナビゲーションは内容に合わせて折り返す

メニュー項目が少なければ、Flexboxのflex-wrap: wrapで折り返すだけでも対応できます。すべてのサイトにハンバーガーメニューが必要なわけではありません。

.nav-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 0;
  padding: 16px;
  list-style: none;
}

項目が多く、開閉式メニューにする場合は、キーボード操作、フォーカス移動、開閉状態を伝えるaria-expandedなども必要です。見た目だけでなく、操作できる仕組みまで確認してください。

レスポンシブ表示を確認する方法

コードを書いたら、特定の端末幅だけでなく、幅を連続的に変えて確認します。ブレークポイントの直前と直後も忘れずに見てください。

ブラウザ幅を直接変える

最も簡単なのは、ブラウザの右端をドラッグして幅を狭める方法です。横スクロール、文字の重なり、画像のはみ出し、余白の不足がないか、ページ下部まで確認します。

開発者ツールのデバイス表示を使う

ChromeやEdgeなどの開発者ツールには、画面幅を指定してスマートフォン表示を確認する機能があります。WindowsではCtrl + Shift + I、macOSではCommand + Option + Iで開発者ツールを開けます。

デバイスツールバーを有効にし、幅を320px程度からデスクトップ幅まで動かします。端末プリセットだけでなく、間の幅でも崩れないかを確認することが大切です。

実機でも操作を確認する

開発者ツールは画面幅の確認に便利ですが、実際のタップ操作、文字の読みやすさ、入力フォーム、画面回転までは完全に同じではありません。公開前には、可能な範囲でスマートフォンやタブレットでも確認します。

レスポンシブ対応でよくある失敗

  • viewportのmetaタグを書いていない
  • 親要素や画像の幅を固定pxのままにしている
  • メディアクエリの波括弧が閉じていない
  • min-widthmax-widthの条件を取り違えている
  • PC・タブレット・スマホという端末名だけでブレークポイントを増やしすぎている
  • 横並びを視覚的に変えても、HTMLの読み順が不自然なままになっている
  • 拡大操作を禁止している
  • 特定のプリセット幅だけ確認し、その間の幅を確認していない

横スクロールが出た場合は、開発者ツールで幅の大きい要素を探します。固定幅、長いURL、white-space: nowrap、余白を含めて100%を超える要素などが主な原因です。

まとめ

HTMLのレスポンシブ対応は、viewport、柔軟な幅、メディアクエリの3つが基本です。まず狭い画面で読みやすい1列を作り、十分な幅がある場合だけカードやサイドバーを横に並べます。

コードを書いたあとは、ブラウザ幅を連続的に変え、横スクロールや文字の重なりがないか確認してください。端末の名前ではなく、内容が読みづらくなる位置を基準にブレークポイントを決めると、幅広い画面へ対応しやすくなります。