はじめに
レスポンシブデザインのWebページを制作する際、CSSのメディアクエリで指定した条件(ブラウザ幅などのブレークポイント)に応じてJavaScriptの処理を実行させたい場面があります。
ブラウザ幅の変化を扱う場合、古くは「window の resize イベントを監視してブラウザ幅を取得する」といった手法も取られていましたが、パフォーマンスなどを考慮した場合には少し実装に工夫が必要でした。
IE10以降の主要なブラウザであれば window.matchMedia メソッド を利用することでシンプルな実装が可能です。
window.matchMedia メソッドを利用した実装
例として、ブラウザ幅 769px をブレークポイントとする場合を考えると、JavaScriptのコードは次のようになります。
// 1. 変数mqlにMediaQueryListを格納
const mql = window.matchMedia('(min-width: 769px)');
// 2. メディアクエリに応じて実行したい処理を関数として定義
const handleMediaQuery = function(mql) {
if (mql.matches) {
// 769px以上の場合の処理
console.log('769px以上');
} else {
// 769px未満の場合の処理
console.log('769px未満');
}
};
// 3. イベントリスナーを追加(メディアクエリの条件一致を監視)
mql.addListener(handleMediaQuery);
// 4. 初回チェックのため関数を一度実行
handleMediaQuery(mql);
大きく4つの処理に分かれているので、1つずつ内容を追ってみます。
1. 変数mqlにMediaQueryListを格納
const mql = window.matchMedia('(min-width: 769px)');
console.log(mql); // MediaQueryList {media: "(min-width: 769px)", matches: true, ...}
まず、Webページ上で利用したいメディアクエリを引数として window.matchMedia メソッドを実行します。
window.matchMedia メソッドの実行により MediaQueryList オブジェクトが生成されるので、それを変数 mql に格納しています。
MediaQueryList オブジェクトは matches というプロパティを持っており、メディアクエリに一致した条件下では true が、一致しない条件下では false が格納されます。
2. メディアクエリに応じて実行したい処理を関数として定義
const handleMediaQuery = function(mql) {
if (mql.matches) {
// 769px以上の場合の処理
console.log('769px以上');
} else {
// 769px未満の場合の処理
console.log('769px未満');
}
};
ここでは handleMediaQuery という関数を定義し、前述した matches プロパティの値(true or false)によって実行したい処理を書き分けています。
3. イベントリスナーを追加(メディアクエリの条件一致を監視)
mql.addListener(handleMediaQuery);
MediaQueryList オブジェクトの addListener メソッドでイベントリスナーを設定できます。
MediaQueryList.matches が変化するタイミング(今回の例ではブラウザ幅が769pxを越えるタイミング)で、引数に指定した handleMediaQuery 関数が実行されます。
4. 初回チェックのため関数を一度実行
handleMediaQuery(mql);
Webページの初期状態でメディアクエリに応じた処理をおこなうため、一度 handleMediaQuery 関数を実行しています。
ここまでのJavaScriptコードを実行すると、ブラウザ幅に応じてコンソールに 769px以上 / 769px未満 というメッセージが表示されることを確認できるかと思います。
ブレークポイントの通過をカスタムイベントとして扱う
メディアクエリの条件一致チェックの際に カスタムイベント を発生させておくことで、ブレークポイントの通過(例えばPCビューとモバイルビューの切り替え)をWebページ上での一つのイベントとして取り扱うことができます。
カスタムイベントの利用にはjQueryの trigger / on メソッドが便利です。
jQueryでカスタムイベントを利用する(.on() と .trigger())
const mql = window.matchMedia('(min-width: 769px)');
const handleMediaQuery = function(mql) {
// カスタムイベント 'breakpoint-{type}' を発火
if (mql.matches) {
$(window).trigger('breakpoint-large');
} else {
$(window).trigger('breakpoint-small');
}
};
mql.addListener(handleMediaQuery);
handleMediaQuery(mql);
function doSomething() {
$(window).on('breakpoint-large', function() {
// 769px以上の場合の処理
console.log('769px以上');
});
$(window).on('breakpoint-small', function() {
// 769px未満の場合の処理
console.log('769px未満');
});
}
doSomething();
上記の例では、doSomething 関数内でカスタムイベントを利用し、ブラウザ幅に応じた処理を実行しています。
参考リンク
Can I use... matchMedia
window.matchMedia - Web API | MDN
MediaQueryList - Web API | MDN