HTML5 アプリケーションをビルドする

CSS3 メディア クエリを使用して応答性の高い Web をビルドする

Brandon Satrom

コード サンプルのダウンロード

この記事では Internet Explorer 10 Platform Preview を取り上げており、記載している情報は変更されることがあります。

数年前、技術に詳しい若いユーザー ベースを対象としたモバイル専用の Web サイトをビルドしたいという話がクライアントからありました。このプロジェクトは、実際 "iPhone サイト" としてうたわれ、しっかり考えられたデザインになっていました。私たちは、このような最先端モバイル アプリを作成することに興奮を覚え、作業に本格的に着手し、順調に進めていきました。しかし、作業もかなり進んでから、市場の他のモバイル デバイスにも対応できないかと考えるようになりました。クライアントも、ほぼすべてのモバイル デバイスをサポートすることを望みました。そして、こうした取り組みの中で、モバイル対応のエクスペリエンスをビルドしようとする Web 開発者が直面するであろう最も重要な 2 つの疑問にぶつかり、その答えを見つけるため多くの努力を行ってきました。疑問の 1 つは、特定のモバイル ブラウザーに合わせてエクスペリエンスを変更するタイミングを知る方法です。もう 1 つは、必要な変更に取り組む方法です。

レスポンシブ Web デザイン

この疑問点を中心に据えたのが、レスポンシブ Web デザイン (Responsive Web Design) です。この用語は、Ethan Marcotte (bit.ly/aO2cFa、英語) が作り出したものです。レスポンシブ Web デザインとは、ブラウザーからコンテキストの手掛かりを得て、ユーザーへのサイトの表示方法や、サイトの動作方法を調整することです。そのデバイスでのユーザーの操作エクスペリエンスに合わせてカスタマイズした魅力的なエクスペリエンスで、ブラウザーが提示する情報に応答することです。適切な手掛かりによって対象のブラウザーやデバイスに関する十分な情報が明らかになれば、代替画像や流動レイアウトなどのカスタマイズを提供できるようになることです。

従来は、ブラウザーが提示するユーザー エージェント文字列を解析することによってこのようなコンテキストの手掛かりを得 (ブラウザー スニッフィングまたは UA スニッフィングと呼びます)、その情報を使用して処理の進め方を判断していました。2011 年 9 月の記事「取り残されるブラウザーをなくす: HTML5 の導入戦略」(msdn.microsoft.com/magazine/hh394148) で、この UA スニッフィングについて説明しました。その記事で述べたように、ブラウザー スニッフィングは信頼性が低く、事実上 "機能検出" に取って代わられました。機能検出は、特定のブラウザーやバージョンではなく、使用可能な機能に基づいて、マークアップ、CSS、および JavaScript に関する決定を下すのに役立ちます。

レスポンシブ Web デザインの観点では、最近のすべてのデスクトップ ブラウザーや多くモバイル ブラウザーが "メディア クエリ" という機能をサポートします。メディア クエリは、サイトにアクセスしているデバイスの物理特性の一部を特定する機能と共に CSS 2.1 で導入されたメディア タイプという考え方を拡張した CSS3 モジュールです。メディア タイプとは、印刷や画面などに合わせて代替スタイル シートを指定する機能です。機能検出を使用するのと同じ理由で、メディア クエリでは、サイトに現在アクセスしているユーザーのコンテキストに関する適切な手掛かりを得ることに重点を置き、この手掛かりに応じて提供するエクスペリエンスを調整します。メディア クエリでは、このような手掛かりがスタイル シートに指定されます。

今回は、CSS3 モジュールのメディア クエリの概要を説明します。メディア クエリの構文と使用法について簡単に説明してから、メディア クエリを使用してオンライン フォト ギャラリー用のビューをスマートフォンとタブレットに合わせてビルドする簡単な例を示します。最後に、あらゆる形式のモバイル開発に不可欠なヒントを共有してから、メディア クエリ リスナーについて簡単にまとめます。メディア クエリ リスナーとは、World Wide Web コンソーシアム (W3C) の独立した仕様 (bit.ly/wyYBDG、英語) で、JavaScript を通じてメディア環境の変化に対応するための API を提供します。この記事を読み終えるころには、CSS といくつかの調整されたスタイルのみを使用して応答性の高い Web サイトとアプリを作成するための強固な基盤が得られます。

CSS メディア クエリ

前に述べたように、現在、CSS 2.1 では、"メディア タイプ" の宣言 (bit.ly/xhD3HD、英語) に基づく、メディア依存のスタイル シートがサポートされます。以下のマークアップは、メディア タイプを使用して条件付きでスタイル シートを指定する方法を示しています。

<link rel="stylesheet" type="text/css" href="main.css" media="screen" />
<link rel="stylesheet" type="text/css" href="print.css" media="print" />

これらの要素を配置すると、サイトは、印刷プレビュー モードでページが読み込まれるときに、既定の ("screen") スタイル シートとは異なるスタイル シートを読み込みます。この機能はこれまではあまり活用されてきませでしたが有益な機能です。しかし、真に応答性の高い Web サイトをビルドするために使用するコンテキストに関する手掛かりは提供しません。また、メディア タイプの仕様では、10 個のメディア タイプの使用を詳細に規定していますが、すべてのブラウザー ベンダーがこの仕様で規定されたタイプをすべて組み込んでいるわけではありません。

とは言え、"media" 属性には強固な基盤があるため、W3C はその上位にメディア クエリ bit.ly/zbIeDg、英語) を構築することに決めました。メディア クエリでは、media 属性でメディア タイプ (print、screen、all など) を指定するときに、特定のメディア機能 (現在のデバイスの幅、高さ、向き、および画面解像度) に対応しているかどうかをチェックする式を追加できます。以下に、メディア タイプが "screen" で、デバイスの画面幅が少なくとも 800 ピクセルであれば、main.css スタイル シートを読み込む例を示します。

<link rel="stylesheet" media="screen and (min-width: 800px)" href="main.css" />

かっこで囲んだ式がメディア クエリです。左辺はテストするプロパティ (幅) と省略可能な min- 修飾子または max- 修飾子を指定し、右辺はそのプロパティの値を指定します。対象のデバイスまたはブラウザーで少なくとも 800 ピクセルの画面幅があれば、main.css のスタイルが適用されます。条件を満たさなければ、main.css のスタイルは適用されません。これは、メディア クエリが、応答性の高い Web サイトやアプリを作成するのに便利なコンテキストの手掛かりを開発者に提供するしくみを示しています。

メディア クエリを使用する

CSS3 メディア クエリは、主要ブラウザーすべての最新バージョン (bit.ly/wpamib、英語) でサポートされているため、現在は快適に使用できます。サイトでメディア クエリを使用する方法は 3 つあります。1 つ目は、前の例で示したように、スタイル シート全体を条件付きで読み込む方法です。2 つ目は、スタイル シートで @import ディレクティブを使用する方法です。先ほどと同じテストを、今回はインポート ディレクティブとして実行します。

@import url("main.css") screen and (min-width: 800px);

最初の例と同様、このステートメントは現在のデバイスの幅を評価し、この幅が少なくとも 800 ピクセルあれば、main.css を読み込んでそのスタイルを適用します。

3 つ目は、次のように、@media ディレクティブを使用して、CSS でインライン指定されたメディア クエリを使用する方法です。

@media screen and (min-width: 800px) { ... }

この場合、別のファイルでスタイルを定義するのではなく、既存のスタイル シートでスタイルをインライン指定し、適切な場合にだけこれらのスタイルが適用されるように、メディア クエリでこのスタイルをラップします。

ここからは、メディア クエリの動作を、簡単な例から見ていきましょう。このメディア クエリを詳しく試したい方は、サンプル ソース コードを確認してください。または、使い慣れた IDE やテキスト エディターを開いて 図 1 のマークアップを追加します。

図 1 サンプル HTML ドキュメント

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="media.css">
  </head>
  <body>
    <article id="small">This is a small screen</article>
    <article id="medium">This is a medium screen</article>
    <article id="large">This is a large screen</article>
    <article id="landscape">... and you're in landscape mode...</article> 
  </body>
</html>

次に、同じフォルダーに media.css というスタイル シートを作成し、図 2 で定義しているスタイルを追加します。すべての @media ディレクティブをファイルの下部で定義しているのがわかります。スタイル シートを作成する場合は同じようにすることをお勧めします。マークアップで複数のスタイル シートを定義する場合は、メインのスタイル シートの後ろに、特定のスタイル シートの <link> 要素を配置します。CSS のカスケード動作により、おそらく、メディア固有のルールを本来のルールに優先させ、適切に定義する必要があります。以下のサンプルでは、記事のスタイルと body 要素を定義してから、サポートするエクスペリエンスごとに、メディア クエリ (と関連付けらるルール) を続けています。480 ピクセルより幅が狭い画面は 1 つ目のセットのスタイルを受け取り、480 ~ 1024 ピクセル幅の画面は 2 つ目のスタイルを受け取り、1024 ピクセルより幅が広い画面は 3 つ目のスタイルを受け取ります。また、デバイスの向きに関するクエリも追加し、デバイスが横長モードの場合は別のスタイルのセットが適用されるようにしています。

図 2 @media ディレクティブを使ってインライン定義した CSS メディア クエリ

article {
  display: none;
}
body {
  font-size: 24px;
  font-weight: 800;
  color: white;
}
@media screen and (max-width: 480px) {
  body {
    background-color: #ff2a18;
  }
  #small {
    display: inline;
  }
}
@media screen and (min-width: 480px) and (max-width: 1024px) {
  body {
    background-color: #00ff00;
  }
  #medium {
    display: inline;
  }
}
@media screen and (min-width: 1024px) {
  body {
    background-color: #0000ff;
  }
  #large {
    display: inline;
  }
}
@media screen and (orientation: landscape) {
  body {
    background-color: #ff7f00;
  }
  #landscape {
    display: inline;
  }
}

図 1 のページと図 2 のスタイル シートを作成したら、任意のブラウザーでこのページを開きます。メディア クエリのテストは簡単です。モバイル デバイスがなくてもテストできます。ブラウザー ウィンドウのサイズを変更して、表示ウィンドウが変化したというコンテキストを作り出し、テキストと背景色がどのように変化するかを確認します。

メディア クエリの基礎を理解したところで、さらに 1 歩進み、より現実的な例を取り上げます。この例では、メディア クエリをオンライン フォト ギャラリーに追加して、スマートフォンとタブレットをサポートできるようにします。この例のコードは、archive.msdn.microsoft.com/mag201204HTML5 にあり、WebMatrix (webmatrix.com) に同梱のフォト ギャラリー テンプレートを使用しています。

このページをモバイルまたはタブレットのブラウザーで開くと、ページが "縮小表示" され、判読しにくいことがわかります (図 3 参照)。いくつかのメディア クエリと、その他いくつかの手法を使用するだけで、新しいマークアップやいかなる種類のブラウザー スニッフィングも使用することなく、調整されたエクスペリエンスを生み出すことができます。

Mobile View Without Media Queries
図 3 メディア クエリを使用しないモバイル ビュー

このサンプル用に作成した desktop.css ファイルの一番下に、まず、メディア クエリのディレクティブと条件を追加します。現在の懸念は最も小さい画面なので、以下の定義を指定します。

@media screen and (max-width: 480px) {}

ここで、その定義内に、より小さい画面向けに画像のサイズ変更と再配置を行うルールをいくつか作成します。このルールを図 4 に示します。

図 4 モバイル デバイス向けのスタイル変更

body {
  min-width: 120px;
  max-width: 320px;
}
h1 {
  font-size: 1.5em;
}
img {
  width: 250px;
  height: 187.5px;
}
ul.thumbnails li {
  width: 265px;
    height: 200px;
    line-height: 200px;
}
ul.thumbnails li span.image-overlay {
    width: 265px;
}

これらのスタイルを追加した後にページを更新すると、図 5 のような画面が表示されます。画像は見やすくなりましたが、メイン ナビゲーションが不揃いになっています。さらに、このギャラリーでは CSS の :hover 擬似セレクターを使用して、各画像に関する追加情報を表示しています (図 6 参照)。これは、ホバー イベントがあまり一般的ではない環境 (スマートフォンやタブレット) では意味のないユーザー エクスペリエンスなので、この点についても代替表示を考える必要があります。そのため、図 7 のスタイルを、現在の @media ディレクティブ内に追加します。

Mobile View with Improved Images
図 5 画像が改善されたモバイル ビュー

An Image with the Hover Effect Applied
図 6 ホバー効果が適用された画像

図 7 モバイル対応ナビゲーションと画像情報のスタイル

#banner {
  height: 110px;
  background: #eaeaea;
}
#menu li {
  display: block;
  margin-top: 3px;
  margin-bottom: 3px;
}
#menu li.tags a,
#menu li.galleries a,
#menu li.account a {
  background: none; 
}
#menu li.login {
  display: none;
}
ul.thumbnails li span.image-overlay {
  display:block;
  position: absolute;
  top: 0;
  left: 0;
  line-height: normal;
  width: 515px;
    padding: 5px;
}
ul.thumbnails li {
    background: #f3f6f7;
    border-color: #dbe2e5;
    border-radius: 7px;
    box-shadow: 0px 0px 20px 5px #A9A9A9;
}

ここで、ブラウザーのページを更新すると、図 8 のように、ナビゲーションが整理され、先ほどホバー イベントで表示された情報も同時に表示されます。

The Gallery with Better Navigation and Image Boxes
図 8 ナビゲーションと画像のボックスが改善されたギャラリー

ここまでは、ギャラリーのデスクトップ表示と、適切なモバイル バージョンがあったので、いくつか追加の CSS ルールがあれば問題ありませんでした。ここでさらに 1 歩進め、480 ピクセルより広く 1024 ピクセルより狭い画面 (タブレット) のサポートを追加しましょう。

フォト ギャラリーをデスクトップ ブラウザーで表示している場合に、1024 ピクセルよりも狭いサイズ (図 8 の画面) に変更すると、多くの画像が切り取られることがわかります。一般的に、タブレット デバイスの画面の幅は広いので、ギャラリー ページにより大きい画像を表示するのが妥当です。そこで、タブレット サイズのデバイス向けに、もう 1 つメディア クエリを追加します。

@media screen and (min-width:480px) and (max-width:1024px)

オンライン ソースでは、スマートフォンのいくつかのルールを、デスクトップ デバイス以外のすべてのデバイスに適用する一連のスタイルにリファクタリングしたので、タブレットの表示に設定する必要があるのは、ドキュメント、画像、およびサムネイルのサイズに関連するスタイルだけです (図 9 参照)。

図 9 タブレット対応のビューのスタイル

body {
  min-width: 480px;
  max-width: 800px;
} 
img {
  width: 500px;
  height: 375px;
  align: center;
} 
ul.thumbnails li {
  width: 515px;
    height: 390px;
    line-height: 200px;
}

ここで、タブレット表示ブラウザーの画面を更新すると、図 10 のような画面が表示されます。現時点では、複数の画面サイズ (および複数のデバイス) を対象にしているので、必要なのは、いくつかの代替スタイルを作成するための時間だけでした。

Photo Gallery, Tablet-Friendly View
図 10 タブレット対応画面のフォト ギャラリー

モバイル優先

メディア クエリに関する説明をまとめる前に、メディア クエリの使用に限らず、あらゆる種類のモバイル Web 開発を行う場合に重要なヒントを確認しておきます。それは、モバイルのビューポートとデザインを優先することです。

この記事のメディア クエリに関するチュートリアルに従ってコードを記述していた方は、スマートフォンまたはスマートフォン エミュレーターでページを表示するときにちょっとした問題が起こったかもしれません。デバイスによっては、条件付きルールを適用した後でも、"縮小表示" 効果が変化しないものもあります。これは、モバイル ブラウザーはより小さい画面でエクスペリエンスを "最適化" しようとするためです。これは、モバイル ユーザーを考慮しないサイトでは有効です。ただし、このサイトでは、このような最適化を行わないという考え方なので、次のように、ページの <head> に 1 つの <meta> タグを追加してこの動作をオーバーライドします。

<meta name="viewport" content="width=device-width">

ここで、ページを更新します。メディア クエリが適切に定義されていると、ルールが実行されていることがわかります。

また、フォト ギャラリーの例では、既存のサイトにモバイル エクスペリエンスを追加しています。メディア クエリについて精通している開発者は、おそらく最初はこのように対処します。しかし、現在の Web サイトやおよびアプリの設計と開発では、"モバイル優先" の手法を重視する動きが高まりつつあります。モバイル優先はその名のとおり、モバイル エクスペリエンスを (従来、多くの場合に行われていたように) 後から考えるのではなく、最優先に考えます。ここ 2 年間を振り返ってみると、スマートフォンとタブレットの販売台数は PC の販売台数を上回り、モバイル デバイスによる閲覧はすべての Web 閲覧の半分以上を占めるようになってきています。さらに、モバイル優先という考え方は "プログレッシブ エンハンスメント" を促進します。つまり、基準となる (多くの場合テキストのみの) エクスペリエンスからサイトを構築し、より多くの使用可能なブラウザーやデバイスに合わせて徐々に強化していきます。モバイル優先手法の詳細については、Luke Wroblewski の著書『Mobile First』(bit.ly/zd9UWT、英語) を強くお勧めします。

メディア クエリ リスナー

CSS3 のメディア クエリ サポートの拡張機能として、CSS ワーキング グループは JavaScript API の追加を検討しています。この API により、開発者は、実行時にメディア クエリを評価して、メディア クエリ条件の実行時の変化をリッスンできます。これらの API は、CSSOM View Module の仕様 (bit.ly/w8Ncq4、英語) で文書化されています。図 11 に、JavaScript 内からメディア クエリを実行してリスナーを作成する例を示します。

図 11 メディア クエリ リスナーの操作

listener = window.msMatchMedia("(min-width: 480px)");
evaluate(listener); // Perform an initial evaluation
listener.addListener(evaluate); // Evaluate each time the width changes
 function evaluate(listener) {
   if (mql.matches) {
    expandCommentList(); // Screen is at least 480px
   } else {
     shrinkCommentList(); // Screen is smaller
   }
 }

リスナーは、デバイスのビューポイントが実行時に変化する可能性がある場合 (たとえば、スマートフォンやタブレットで向きが変わる場合など) に有効です。メディア クエリ リスナーを使用すると、CSS 内からだけでなく、スクリプト内からこのような変化に対応できます。CSSOM View の仕様は、現時点では草案状態ですが、Internet Explorer 10 Platform Preview はメディア クエリ リスナーのサポートを提供するため、Internet Explorer Test Drive (bit.ly/gQk7wZ、英語) で確認できます。

Web アプリケーションで複数のプラットフォーム、画面、およびエクスペリエンスをサポートする機能は、ここ数年で大きな発展を遂げてきました。従来は、サイトのデバイス固有のバージョンを作成することが一般的でしたが、モバイル対応デバイスの急増により、デバイス固有のバージョンを作成することはすぐに現実的ではなくなりました。さいわい、すべての主要デスクトップ ブラウザーとモバイル ブラウザーに CSS3 メディア クエリが導入されたことでコンテキストの手掛かりを利用できるようになりました。これは、条件付き CSS を使用してさまざまなデバイスに合わせて調整したエクスペリエンスを提供するために非常に重要です。CSS3 メディア クエリの詳細については、Peter Gasston のすばらしい著書『The Book of CSS3』(No Starch Press、2011 年、英語) のメディア クエリに関する章を参照してください。メディア クエリのヘルプと共に提供され、優れたエクスペリエンスを例示するギャラリーについては、メディア クエリのサイトを参照してください。今回の記事によって、調整されたエクスペリエンスの構築にすぐに着手するのに十分な情報を提供できていればさいわいです。皆さんが作成した最高のエクスペリエンスを見られるのを楽しみにしています。

Brandon Satrom は、Telerik の HTML5 およびモバイルのツールセットである、Kendo UI (kendoui.com、英語) のプロダクト マネージャーです。彼のブログは userinexperience.com (英語) です。Twitter のアカウントは @BrandonSatrom (英語) です。

この記事のレビューに協力してくれた技術スタッフの John BoxSharon Newman、および Jacob Rossi に心より感謝いたします。