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

インターネットでスマートフォンを使用するユーザーが増えるにつれ、ウェブデザイナーにとって、さまざまな画面サイズで適切に機能するようにコンテンツをレイアウトすることがますます重要になっています。レスポンシブ ウェブデザインは、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 の関係を設定するようブラウザに指示します。

width または initial-scale を含む <meta name="viewport"> タグがない: Lighthouse の監査を使用すると、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 の高さ向きaspect-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 メニューを開き、[メディアクエリを表示] を選択します。ページ上にブレークポイントがカラーバーとして表示されます。
  4. バーを 1 つクリックすると、そのメディアクエリが有効になった状態のページが表示されます。バーを右クリックすると、そのメディアクエリの定義にジャンプします。