はじめに
レスポンシブデザインの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