テーブルタグがCSSに変わり、レスポンシブデザインは心躍るコンセプトの1つです。レスポンシブデザインはメディアクエリで閲覧中の機器の画面幅、高さ、向き、解像度、アスペクト比、色深度などを把握し、応じたスタイルシートを適用しています。
以下の例はcssbasic.cssをすべてのデバイスに適用して、水平方向の画面幅が500ピクセル以上なら、csswide.cssも適応します。
<link rel="stylesheet" media="all" href="cssbasic.css" />
<link rel="stylesheet" media="(min-width: 500px)" href="csswide.css" />
インターネット上の多くのWebサイトがメディアクエリを活用しています。ブラウザーの幅を変えれば、Webページのレイアウトも変化します。
メディアクエリで、CSSによるデザイン分岐や要素のサイズ変更が容易になりましたが、小さな画面の場合だけ短いヘッドラインを表示したり、JavaScriptライブラリーの利用を減らしたり、ウィジェットの動作を変更したり、コンテンツや機能を変更したりするにはどうすれば良いでしょう?
JavaScriptでviewportサイズを調べるのは少し手間です。
- 大半のブラウザーはwindow.innerWidthやwindow.innerHeightに対応している
- しかしIE6、7、8、9の互換モードでは、document.body.clientWidthおよびdocument.body.clientHeightの記述が必要
- window.onresize
- 主要ブラウザーはdocument.documentElement.clientWidthおよびdocument.documentElement.clientHeightに対応しているが、一貫しない。ブラウザーやモードにより、ウィンドウ幅が返ってきたりドキュメントサイズが返ってきたりする
うまくviewportのサイズ変更を検知しても、向きや縦横比などを計算しなければなりません。さらにCSSのメディアクエリのルールを適用したとき、計算が想定した通りに反映される保証はありません。
JavaScriptにおけるメディアクエリの書き方
JavaScriptでCSS3メディアクエリのステート変化に対応できます。鍵になるAPIはwindow.matchMediaです。CSSメディアクエリと同じ「メディアクエリ文字列」が渡されます。
const mq = window.matchMedia( "(min-width: 500px)" );
matchesプロパティは問い合わせの結果に応じてtrueもしくはfalseを返します。
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
変更を検知したときに実行するイベントリスナーを追加できます。
// media query event handler
if (matchMedia) {
const mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
}
イベント定義後にイベントハンドラを直接呼ぶため、ページが読み込まれる間もしくは読み込み後にコードを初期化します。ユーザーがブラウザーの大きさを変更しない限りWidthChange()は呼ばれません。
執筆時点ではmatchMediaは主要ブラウザーの多くで対応しています。本番サイトで使わない手はありません。
以下のデモでブラウザーのサイズを変えるか、サンプルコードをダウンロードして、横幅が500ピクセル以上の場合とそれより小さい場合とで文字の表示が変化するのを確かめてください。
※2011年10月12日に公開した記事を更新しました。変更点は最新情報の追加、冒頭画像の追加、CodePenデモです。
(原文:How to use Media Queries in JavaScript)
[翻訳:西尾 健史/編集:Livit]