レスポンシブ ウェブ デザインの基本

ユーザーが閲覧するデバイスのニーズと機能に応じたサイトを作成する方法。

モバイル デバイスでのウェブ ブラウジングは、天文学的なペースで増え続けています。こうしたデバイスはディスプレイ サイズによる制約を受けることが多く、画面上のコンテンツの配置方法にも異なるアプローチが必要になります。

レスポンシブ ウェブ デザインは元々 Ethan Marcotte が A List Apart と定義し、ユーザーのニーズとユーザーが使用しているデバイスに対応できます。レイアウトはデバイスのサイズと機能に応じて変わります。たとえば、スマートフォンではコンテンツが 1 列で表示されますが、タブレットでは同じコンテンツが 2 列で表示されます。

この動画では、画面の表示領域に合わせて、ビューポートが狭い状態から広いビューポートに変化しています。

スマートフォン、ファブレット、タブレット、パソコン、ゲーム機、テレビ、さらにはウェアラブルまで、さまざまな画面サイズが存在します。画面サイズは常に変化するため、現在または将来、あらゆる画面サイズにサイトが適応できるようにすることが重要です。また、デバイスには、私たちが操作するさまざまな機能があります。たとえば、訪問者の中にはタッチスクリーンを使用する人もいます。最新のレスポンシブ デザインでは、これらすべての要素を考慮してエクスペリエンスを最適化しています。

ビューポートを設定する

さまざまなデバイス向けに最適化されたページでは、ドキュメントのヘッダーにメタ ビューポート タグを含める必要があります。メタ ビューポート タグは、ページのサイズとスケーリングの制御方法をブラウザに指示するものです。

最適なエクスペリエンスを実現するため、モバイル ブラウザはパソコン画面の幅(通常は約 980px。ただし、デバイスによって異なりますが、デバイスによって異なります)でページをレンダリングし、フォントサイズを大きくしてコンテンツを画面に合わせて拡大縮小することで、コンテンツの見栄えも良くします。そのため、ユーザーにとってフォントサイズが一貫していないように見えることがあります。ユーザーは、コンテンツを表示して操作するために、ダブルタップやピンチ操作によるズーム操作が必要になることがあります。

<!DOCTYPE html>
<html lang="en">
  <head>
    …
    <meta name="viewport" content="width=device-width, initial-scale=1">
    …
  </head>
  …

メタ ビューポートの値 width=device-width を使用すると、画面の幅をデバイス非依存ピクセルで一致させるようにページに指示します。デバイス(または密度)に依存しないピクセルは、単一のピクセルを表します。高密度画面では、多くの物理ピクセルで構成される場合があります。これにより、小さなスマートフォンや大型のデスクトップ モニターなど、さまざまな画面サイズに合わせてページのコンテンツをリフローできます。

非常にズームアウトしたためにテキストが読みにくいページのスクリーンショット。
ビューポート メタタグのないデバイスでのページの読み込み方法の例。Glitch の例をご覧ください
同じページのスクリーンショット。テキストが読みやすいサイズで表示されます。
ビューポート メタタグのあるデバイスでページが読み込まれる方法の例。Glitch の例をご覧ください

一部のブラウザでは、横表示に回転してもページの幅が一定に保たれ、リフローではなくズームで画面全体に表示されます。値 initial-scale=1 を追加すると、デバイスの向きに関係なく CSS ピクセルとデバイス非依存ピクセルの間に 1 対 1 の関係を確立するようブラウザに指示され、ページで横向きの全幅を利用できます。

Lighthouse の監査機能は、width または initial-scale を含む <meta name="viewport"> タグがないもので、HTML ドキュメントでビューポート メタタグが正しく使用されているか確認するプロセスを自動化できます。

アクセス可能なビューポートを確保する

ビューポートには、initial-scale の設定に加えて、次の属性も設定できます。

  • minimum-scale
  • maximum-scale
  • user-scalable

これらを設定すると、ユーザーがビューポートをズームできなくなり、ユーザー補助の問題が発生する可能性があります。そのため、これらの属性の使用はおすすめしません。

コンテンツのサイズをビューポートに合わせる

パソコンとモバイル デバイスのどちらでも、ユーザーはウェブサイトを水平方向ではなく垂直方向にスクロールすることに慣れています。ページ全体を表示するためにユーザーが水平方向にスクロールしたりズームアウトしたりしなければならないと、ユーザー エクスペリエンスが低下します。

メタ ビューポート タグを使用してモバイルサイトを開発している場合、指定されたビューポートに収まらないページ コンテンツを誤って作成してしまう可能性が高くなります。たとえば、ビューポートよりも広い幅で表示される画像によって、ビューポートが水平方向にスクロールすることがあります。ユーザーが水平方向にスクロールしなくても済むように、このコンテンツをビューポートの幅に収まるように調整する必要があります。

コンテンツがビューポートに合わせて適切にサイズ設定されていません。Lighthouse の監査機能は、オーバーフロー コンテンツを検出するプロセスを自動化するのに役立ちます。

画像

画像は固定サイズであるため、ビューポートよりも大きい場合はスクロールバーが表示されます。この問題への一般的な対処方法は、すべての画像に 100%max-width を指定することです。これにより、ビューポート サイズが画像よりも小さい場合、画像がスペースに収まるように縮小されます。ただし、width ではなく max-width100% であるため、画像が元のサイズより大きく引き伸ばされることはありません。スクロールバーを引き起こす画像で問題が発生しないようにするために、一般的にはスタイルシートに以下を追加しても安全です。

img {
  max-width: 100%;
  display: block;
}

img 要素に画像のサイズを追加する

max-width: 100% を使用する場合、画像の実サイズをオーバーライドしますが、<img> タグでは width 属性と height 属性を使用する必要があります。最新のブラウザでは、この情報を使用して画像の読み込み用のスペースが確保されるため、コンテンツが読み込まれる際のレイアウト シフトを回避できます。

レイアウト

画面のサイズと CSS ピクセルの幅はデバイスによって大きく異なるため(スマートフォンとタブレット、さらにはスマートフォン間でも異なるため)、コンテンツを適切にレンダリングするために、特定のビューポートの幅に依存しないようにしてください。

以前は、この必須設定要素を使用して、パーセンテージでレイアウトを作成していました。 以下の例では、ピクセルを使用してサイズが設定されたフローティング要素を含む 2 列レイアウトを示しています。ビューポートが列の合計幅より小さくなったら、コンテンツを表示するために水平方向にスクロールする必要があります。

2 列目のほとんどがビューポートの外側にある 2 列レイアウトのスクリーンショット
ピクセルを使用したフローティング レイアウト。Glitch の例をご覧ください

幅にパーセンテージを使用すると、列は常にコンテナの一定のパーセンテージに保たれます。つまり、スクロールバーが作成されるのではなく、列の幅が狭くなります。

Flexbox、グリッド レイアウト、マルチコルなどの最新の CSS レイアウト手法を使用すると、こうした柔軟なグリッドを簡単に作成できます。

Flexbox

このレイアウト方法は、サイズの異なるアイテムのセットがあり、それらを 1 行または 1 行に無理なく収め、小さいアイテムはスペースが小さく、大きいアイテムはスペースが大きくなる場合に適しています。

.items {
  display: flex;
  justify-content: space-between;
}

レスポンシブ デザインでは、Flexbox を使用してアイテムを 1 行として表示したり、使用可能なスペースの縮小に合わせて複数の行に折り返すことができます。

Flexbox の詳細

CSS グリッド レイアウト

CSS グリッド レイアウトを使用すると、柔軟なグリッドを簡単に作成できます。 前述のフローティングの例では、パーセントで列を作成するのではなく、グリッド レイアウトと、コンテナ内で使用可能なスペースの一部を表す fr ユニットを使用できます。

.container {
  display: grid;
  grid-template-columns: 1fr 3fr;
}

グリッドは、適切な数のアイテムを配置した通常のグリッド レイアウトの作成にも使用できます。画面サイズが縮小するにつれ、利用可能なトラックの数は少なくなります。 以下のデモには、各行に収まる数枚のカードがあり、最小サイズは 200px です。

CSS グリッド レイアウトの詳細

複数列レイアウト

レイアウトのタイプによっては、複数列レイアウト(マルチ列)を使用できます。このレイアウトでは、column-width プロパティを使用してレスポンシブな列数を作成できます。以下のデモでは、別の 200px 列を追加する余地がある場合は、列が追加されることがわかります。

Multicol の詳細

CSS メディアクエリを使用して応答性を高める

場合によっては、特定の画面サイズをサポートするために、上記の手法では許容できない範囲でレイアウトに大幅な変更を加えることが必要になる場合があります。ここでメディアクエリが役立ちます。

メディアクエリは、CSS スタイルに適用できるシンプルなフィルタです。コンテンツをレンダリングするデバイスの種類、またはそのデバイスの機能(幅、高さ、向き、ホバー機能、デバイスがタッチスクリーンとして使用されているかどうかなど)に基づいて、スタイルを簡単に変更できます。

さまざまな印刷スタイルを指定するには、出力タイプを指定して、次のように印刷スタイルを持つスタイルシートを含める必要があります。

<!DOCTYPE html>
<html lang="en">
  <head>
    …
    <link rel="stylesheet" href="print.css" media="print">
    …
  </head>
  …

また、メディアクエリを使用して、メインのスタイルシート内に印刷スタイルを追加することもできます。

@media print {
  /* print styles go here */
}

レスポンシブ ウェブ デザインでは、通常、小さな画面用に別のレイアウトを提供するために、または訪問者がタッチスクリーンを使用していることを検出したときに、デバイスの機能をクエリします。

ビューポートのサイズに基づくメディアクエリ

メディアクエリを使用すると、小画面、大画面、その中間に特定のスタイルが適用されるレスポンシブなユーザー エクスペリエンスを実現できます。したがって、ここで検出されている機能は画面サイズであり、以下をテストできます。

  • widthmin-widthmax-width
  • heightmin-heightmax-height
  • orientation
  • aspect-ratio

これらの機能はすべて、優れたブラウザ サポートを備えています。ブラウザのサポート情報などの詳細については、MDN の高さ向きアスペクト比をご覧ください。

デバイスの機能に基づくメディアクエリ

利用可能なデバイスが多様であるため、大型デバイスすべてが通常のデスクトップ パソコンやノートパソコンであると仮定することはできません。また、ユーザーが小型デバイスでタッチスクリーンのみを使用しているとも限りません。メディアクエリの仕様に追加されたいくつかの新しい機能により、デバイスの操作に使用されるポインタの種類や、ユーザーが要素にカーソルを合わせられるかどうかなどの機能をテストできるようになりました。

  • hover
  • pointer
  • any-hover
  • any-pointer

通常のデスクトップ パソコン、スマートフォン、タブレットなど、さまざまなデバイスでこのデモを表示してみてください。

これらの新機能は、すべての最新ブラウザで適切にサポートされています。hover任意のマウスオーバーポインタ任意のポインタの MDN ページをご覧ください。

any-hoverany-pointer の使用

any-hover 機能と any-pointer 機能は、ユーザーがカーソルを合わせられるかどうか、またはそのタイプのポインタがデバイスの操作における主な手段でない場合でも、そのタイプのポインタを使用できるかどうかをテストします。これらを使用するときは特に注意してください。タッチスクリーンを使用しているときにマウスに強制的に切り替えることは、あまり扱いにくい操作です。 ただし、ユーザーが使用しているデバイスの種類を判別することが重要な場合は、any-hoverany-pointer が便利です。たとえば、タッチスクリーンとトラックパッドを備えたノートパソコンは、ホバー機能に加えて、粗いポインタと細いポインタにも対応する必要があります。

ブレークポイントを選択する方法

デバイスクラスに基づいてブレークポイントを定義しないでください。現在使用されている特定のデバイス、製品、ブランド名、オペレーティング システムに基づいてブレークポイントを定義すると、メンテナンスが大変なことになります。代わりに、コンテンツ自体が、コンテナに合わせてレイアウトをどのように調整するかを決定する必要があります。

小規模から開始して、徐々に大きなブレークポイントを設定する

最初に小さい画面サイズに合うようにコンテンツをデザインしてから、ブレークポイントが必要になるまで画面を拡大します。これにより、コンテンツに基づいてブレークポイントを最適化し、維持できるブレークポイントの数を最小限にすることができます。

冒頭の例で天気予報を見てみましょう。まず、小さな画面で予測結果が適切に表示されるようにします。

モバイル幅で表示される天気アプリのスクリーンショット
幅が狭いアプリ。

次に、要素間の空白が増え、天気予報の見た目が良くなくなるまで、ブラウザのサイズを変更します。この決定はやや主観的ですが、600px を超える場合は明らかに幅が広すぎます。

アイテム間に大きなギャップがある天気アプリのスクリーンショット
デザインを調整する必要があると感じた時点のアプリ。

600px にブレークポイントを挿入するには、コンポーネントの CSS の末尾に 2 つのメディアクエリを作成します。1 つはブラウザが 600px 以下の場合、もう 1 つは幅が 600px を超える場合に使用します。

@media (max-width: 600px) {

}

@media (min-width: 601px) {

}

最後に、CSS をリファクタリングします。600pxmax-width に対するメディアクエリ内に、小さな画面専用の CSS を追加します。601pxmin-width に対するメディアクエリ内に、大画面用の CSS を追加します。

必要に応じてマイナー ブレークポイントを設定する

レイアウトが大幅に変化したときにメジャー ブレークポイントを選択するだけでなく、小さな変更に合わせて調整することもおすすめします。たとえば、メジャー ブレークポイント間では、要素のマージンやパディングを調整したり、レイアウトに自然に見えるようにフォントサイズを拡大したりすると便利な場合があります。

まず、小画面レイアウトを最適化しましょう。ここでは、ビューポートの幅が 360px より大きいときにフォントを大きくしましょう。次に、十分なスペースがあれば、高温と低温を分けて、互いに重ねるのではなく同じ行に並べます。 また、天気アイコンを少し大きくします。

@media (min-width: 360px) {
  body {
    font-size: 1.0em;
  }
}

@media (min-width: 500px) {
  .seven-day-fc .temp-low,
  .seven-day-fc .temp-high {
    display: inline-block;
    width: 45%;
  }

  .seven-day-fc .seven-day-temp {
    margin-left: 5%;
  }

  .seven-day-fc .icon {
    width: 64px;
    height: 64px;
  }
}

同様に、大画面の場合は、画面の幅全体を使い果たさないように、予測パネルの最大幅に制限することをおすすめします。

@media (min-width: 700px) {
  .weather-forecast {
    width: 700px;
  }
}

読みやすいようにテキストを最適化する

古典的な可読性理論では、理想的な列は 1 行あたり 70 ~ 80 文字(英語では約 8 ~ 10 語)にすることが推奨されています。そのため、テキスト ブロックの幅が約 10 語を超えるたびに、ブレークポイントを追加することを検討してください。

モバイル デバイスでのテキスト ページのスクリーンショット
モバイル デバイスで読み上げられるテキスト。
パソコンのブラウザで表示されたテキストページのスクリーンショット
行の長さを制限するブレークポイントが追加されたパソコンのブラウザで読み上げられるテキスト。

上記のブログ投稿の例を詳しく見てみましょう。 小さい画面では 1em の Roboto フォントは 1 行あたり 10 語で問題なく機能しますが、大きい画面ではブレークポイントが必要です。この場合、ブラウザの幅が 575px より大きい場合、最適なコンテンツの幅は 550px です。

@media (min-width: 575px) {
  article {
    width: 550px;
    margin-left: auto;
    margin-right: auto;
  }
}

コンテンツを単に非表示にすることを回避する

画面サイズに応じてどのコンテンツを表示または非表示にするかは慎重に選択してください。 コンテンツが画面に収まらないという理由だけで、コンテンツを非表示にすることは避けてください。画面サイズは、ユーザーが求めるものを明確に示すものではありません。たとえば、天気予報から花粉飛散量を除外することは、春のアレルギー患者にとって、外出の可否を判断するために情報を必要とする深刻な問題となる可能性があります。

Chrome DevTools でメディアクエリ ブレークポイントを表示する

メディアクエリ ブレークポイントを設定したら、サイトがどのように表示されるかを確認します。ブラウザのウィンドウのサイズを変更してブレークポイントをトリガーすることもできますが、Chrome DevTools には、ブレークポイントが異なるとページがどのように見えるかを簡単に確認できる機能が組み込まれています。

天気情報アプリを開き、幅 822 ピクセルが選択されている DevTools のスクリーンショット。
広いビューポート サイズで天気アプリを表示している DevTools。
天気情報アプリを開き、幅 436 ピクセルが選択されている DevTools のスクリーンショット。
狭いビューポート サイズで天気アプリを表示している DevTools。

さまざまなブレークポイントでページを表示するには:

DevTools を開き、[Device Mode] をオンにします。 デフォルトではレスポンシブ モードで開きます。

メディアクエリを表示するには、[Device Mode] メニューを開いて、[Show media クエリ] を選択し、ブレークポイントをページ上に色付きのバーとして表示します。

バーの 1 つをクリックすると、そのメディアクエリがアクティブなときにページが表示されます。 バーを右クリックすると、メディアクエリの定義にジャンプできます。