JavaScriptによるメディアクエリ「window.matchMedia」
レスポンシブコーディングにおいてCSSのメディアクエリによる分岐は必須ですが、JavaScriptの分岐にもメディアクエリと同じようなものがあるのをご存知でしょうか?
一般的にJavaScriptでブラウザサイズによる条件分岐は$(window).width()やresizeを利用したものが多いですが、サイズ変更のたびに処理を実行するのでパフォーマンスに影響がありました。そこでブレイクポイントのみを監視して切り替わったタイミングで1度だけイベントを発生させるwindow.matchMediaについてご紹介します。
まず$(window).width()やresizeを使った分岐とwindow.matchMediaを使った分岐を比較してみます。
$(window).width()とresizeを使った分岐
$(window).on('load resize', function(){
let w = $(window).width();
if(w <= 768){
// ウィンドウサイズ768px以下のときの処理
}else{
// それ以外の処理
}
});
これでも動きますが、resizeの度に処理が発生してしまいます。また、$(window).width()はスクロールバーを含めたウィンドウの横幅になり、スクロールバーのサイズが異なるブラウザ間で挙動が変わる可能性があります。
window.matchMediaを使った分岐
if (window.matchMedia('(max-width: 768px)').matches) {
// ウィンドウサイズ768px以下のときの処理
} else {
// それ以外の処理
}
window.matchMediaの基本的な記述はこれだけです。あとは変数化してロード時の実行とウィンドウサイズの変更を監視する.addListener()を追加します。
const mediaQuery = window.matchMedia('(max-width: 768px)');
// ページが読み込まれた時に実行
handle(mediaQuery);
// ウィンドウサイズを変更しても実行(ブレイクポイントの監視)
mediaQuery.addListener(handle);
function handle(mm) {
if (mm.matches) {
// ウィンドウサイズ768px以下のときの処理
} else {
// それ以外の処理
}
}
いかがでしょうか。なんといってもブレイクポイント通過時に1度だけ処理されるので無駄な処理がないのが魅力です。
window.matchMediaのデモページ
メリット
- CSSのメディアクエリと同じ書き方ができる(landscapeやportraitも利用可)
- resizeではサイズ変更されるたび中身の処理が行われていたが、matchMediaならブレイクポイントが切り替わる時に一度だけ処理が実行されパフォーマンスが良い
- $(window).width()と違い、スクロールバーを含めないブレイクポイントの処理が可能になるので、スクロールバーの幅の違いによるブラウザ毎の挙動の違いが発生しない
デメリット
Internet Explorer 9 に対応していない。
- Internet Explorer 10 以上
- Firefox 6.0 以上
- Chrome 9.0 以上
- Safari 5.1 以上
- Opera 12.1 以上
- iOS Safari 6.0-6.1 以上
- Android Browser 4 以上
- Blackberry Browser
- Opera Mobile
- Chrome for Android
- Firefox for Android
- Internet Explorer Mobile
モダンブラウザは全て対応していますし、Internet Explorer は現時点でも10までサポート終了しているのでデメリットとは言えないかもしれませんが、対応する必要がある場合も読み込むだけで対応できるスクリプトがあるので安心です。
Internet Explorer9に対応させる方法
https://github.com/paulirish/matchMedia.js/
上記ページからファイルをダウンロードして以下のように事前に読み込むだけです。
<script src="matchMedia.js"></script>
<script src="matchMedia.addListener.js"></script>
まとめ
$(window).width()とresizeを使った分岐でも大抵問題はないのですが、処理によっては動作が重たくなったり、ブラウザ毎の挙動の違いが発生する可能性があります。その場合は今回紹介したwindow.matchMedia()を利用してみてください。細かい範囲のブレイクポイントの指定も簡単ですし、landscapeやportraitといった指定も可能なので、CSSのメディアクエリと同じ感覚で使用できて場合によっては重宝すると思います。
WEBプログラマー / O.K