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

インターネットでスマートフォンを使用するユーザーが増えるにつれ、ウェブデザイナーにとって、さまざまな画面サイズに対応したコンテンツをレイアウトすることがますます重要になっています。レスポンシブ ウェブデザインは、Ethan Marcotte が A List Apart で最初に定義したデザイン戦略で、使用しているデバイスに合わせてサイトのレイアウトを変更することで、ユーザーのニーズとデバイスの機能に対応します。たとえば、レスポンシブ サイトでは、スマートフォンではコンテンツを 1 列のビューで表示し、タブレットでは 2 列で表示し、パソコンでは 3 列または 4 列で表示できます。

画面が広くなると、ウィジェットの形状がそれに応じて変化します。

インターネット対応デバイスにはさまざまな画面サイズがあるため、既存の画面サイズだけでなく、今後登場する画面サイズにも対応できるウェブサイトを構築することが重要です。最新のレスポンシブ デザインでは、タッチスクリーンなどのインタラクション モードも考慮されます。すべてのユーザーにとって最適なエクスペリエンスを提供することが目標です。

ビューポートを設定する

さまざまなデバイス向けにページを最適化するには、ドキュメントの head 部に meta viewport タグを含める必要があります。このタグは、ページのサイズと拡大縮小を制御する方法をブラウザに指示します。

最適なエクスペリエンスを提供するために、モバイル ブラウザではページをパソコンの画面幅(通常は約 980px、ただしデバイスによって異なる)でレンダリングしたうえで、フォント サイズを大きくしたりコンテンツを画面に合わせてスケーリングすることで見栄えが良くなるようにします。この調整により、フォント サイズの統一感が失われることがあります。また、コンテンツを表示して操作するために、ユーザーがズームインする必要がある場合もあります。

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

meta viewport の値 width=device-width を使用すると、画面の幅をデバイス非依存ピクセル(DIP)で合わせるようページに指示が与えられます。これは標準の視覚ピクセル単位で、高密度画面では多くの物理ピクセルで構成されます。これにより、ページのコンテンツをさまざまな画面サイズに合わせてリフローできます。

非常にズームアウトされているため、テキストが読みにくいページのスクリーンショット。
ビューポートのメタタグが設定されていないページは、非常に拡大状態で読み込まれるため、テキストが読みづらくなります。Glitch の例をご覧ください。
同じページのスクリーンショット(テキストが読み取り可能なサイズになっている)。
ビューポート メタタグを設定すると、拡大せずにページを読むことができます。 Glitch の例をご覧ください。

一部のブラウザでは、横向きモードに回転した際もページが同じ幅に保たれ、リフローではなくズームによってコンテンツを画面サイズに合わせます。値 initial-scale=1 を追加すると、デバイスの向きに関係なく CSS ピクセルとデバイス非依存ピクセルとの間に 1:1 の関係を設定するようブラウザに指示が与えられます。これにより、横向きにした場合にページ幅全体を利用できるようになります。

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

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

ユーザーはパソコンとモバイル端末のどちらにおいても、ウェブサイトを縦方向にスクロールすることには慣れていますが、横方向へのスクロールには慣れていません。ページ全体を表示するためにユーザーに横方向へのスクロールやズームアウトをさせることは、ユーザー エクスペリエンスの低下につながります。

meta viewport タグを設定したモバイルサイトを構築する際、特定のビューポートにうまく合わないページ コンテンツを誤って作成してしまうことがよくあります。たとえば、ビューポートよりも広い幅で表示される画像があると、横方向へのスクロールが発生します。これを回避するには、コンテンツをビューポート内に収まるように調整します。

Lighthouse の監査項目「コンテンツのサイズとビューポートのサイズが一致していません」を使用すると、コンテンツのオーバーフロー検出プロセスを自動化できます。

画像

固定サイズの画像がビューポートよりも大きい場合、ページがスクロールされます。すべての画像に max-width100% に設定することをおすすめします。これにより、画像が使用可能なスペースに合わせて縮小され、元のサイズを超えて拡大されなくなります。

ほとんどの場合、スタイルシートに以下を追加することで、この問題を解決できます。

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

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

max-width: 100% を設定する場合でも、<img> タグに width 属性と height 属性を追加することをおすすめします。これにより、ブラウザは画像を読み込む前に画像のスペースを予約できます。これにより、レイアウト シフトを防ぐことができます。

レイアウト

画面サイズと CSS ピクセルの幅はデバイス間(スマートフォンとタブレットの間や、異なるスマートフォン間など)で大きく異なるため、コンテンツを適切に表示するには、特定のビューポートの幅に依存しないようにする必要があります。

以前は、レイアウト要素をパーセンテージで設定する必要がありました。ピクセル単位の測定を使用すると、小さな画面でユーザーが横方向にスクロールする必要があります。

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

代わりにパーセンテージを使用すると、各列が常に画面幅の同じ割合を占めるため、小さい画面では列が狭くなります。

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

Flexbox

サイズの異なるアイテムのセットを 1 行または複数の行に収める場合は、Flexbox を使用します。小さいアイテムはスペースをあまり使用せず、大きいアイテムはスペースを多く使用します。

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

Flexbox を使用すると、アイテムを 1 行として表示したり、使用可能なスペースが減るにつれて複数の行に折り返したりできます。

Flexbox の詳細

CSS グリッド レイアウト

CSS グリッド レイアウトを使用すると、柔軟なグリッドを作成できます。グリッド レイアウトと fr 単位(コンテナ内の使用可能なスペースの一部を表します)を使用すると、前述のフローティングの例を改善できます。

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

グリッド レイアウトを使用して、収まるだけ多くのアイテムを含む通常のグリッド レイアウトを作成することもできます。画面サイズが小さくなると、使用可能なトラック数が減ります。次のデモは、各行に収まるカードをすべて含むグリッドを示しています。最小サイズは 200px です。

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

複数列レイアウト

レイアウトによっては、複数列レイアウト(Multicol)を使用できます。このレイアウトでは、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 の widthheightorientationaspect-ratio をご覧ください。

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

デバイスの種類が非常に多いため、デベロッパーは、大きなデバイスはすべて通常のデスクトップ パソコンまたはノートパソコンであり、小さなデバイスはすべてタッチスクリーンを使用しているとは限りません。メディアクエリ仕様に最近追加された機能を使用すると、デバイスの操作に使用されるポインタのタイプや、ユーザーが要素の上にポインタを保持できるかどうかなどの機能をテストできます。

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

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

これらの新しい機能は、すべての最新ブラウザで十分にサポートされています。詳しくは、MDN のhoverany-hoverpointerany-pointer のページをご覧ください。

any-hoverany-pointer を使用する

any-hoverany-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;
  }
}

コンテンツを非表示にしないこと(:#avoid-hiding-content)

画面サイズに応じてどのコンテンツを表示し、どのコンテンツを非表示にするかを選ぶ際は、注意が必要です。画面に収まらないという理由だけで、コンテンツを単に非表示にすることは避けてください。画面サイズだけで、ユーザーが必要とする情報を判断してはいけません。たとえば、天気予報から花粉情報を削除してしまうと、春先に花粉症に悩む人は、その情報を見て外出の可否の判断を下せなくなるという大きな問題が生じます。

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

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

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

ブレークポイントが異なるページを表示するには、

  1. DevTools を開きます
  2. [デバイスモード] をオンにします。デフォルトではレスポンシブ モードで開きます。
  3. メディアクエリを表示するには、[Device Mode] メニューを開いて [Show media queries] を選択します。ページ上にブレークポイントがカラーバーとして表示されます。
  4. バーを 1 つクリックすると、そのメディアクエリが有効になった状態のページが表示されます。バーを右クリックすると、そのメディアクエリの定義にジャンプします。