matchMediaでメディアクエリのブレイクポイントで条件分岐してみよう!

javascript

メディアクエリと言えばCSSでよく使います。今回はヘッダーを固定させたので、コンテンツが隠れてしまうのを防ぐ為にヘッダーの高さ分の余白をブレイクポイント事に取得する必要がありました。

よくwindow の resize イベントでブラウザ幅を監視してwindow.innerWidthで幅を取得するやり方がありました。
しかしメディアクエリに設定したブレイクポイントをJavaScriptで検知するメソッドがあるので今回はそちらを試してみました。

window.matchMediaとは?

では、どうしたらブレイクポイントを検知できるのかというと、window.matchMediaというメソッドがあります。

指定された メディアクエリ文字列のパース結果を表す、新しい MediaQueryList オブジェクトを返します。

https://developer.mozilla.org/ja/docs/Web/API/Window/matchMedia

基本となるコード

まずは基本となるソースコードを載せます。いろいろサイト見ましたが、ほぼほぼ決まり文句のように同じです。

var mediaQuery = window.matchMedia("(max-width: 896px)");

// ウィンドウサイズが変更されても実行されるように
mediaQuery.addListener(handle);

function handle(mq) {

  if (mq.matches) {
    // ウィンドウサイズが896px以下の時の処理
  } else {
    // それ以外の時の処理
  }
}

// ページが読み込まれた時に実行
handle(mediaQuery);

window.matchMediaでブレイクポイントを指定する

windowオブジェクトのmatchMediaメソッドの引数に検知したいブレイクポイントを指定する。戻り値はMediaQueryList のオブジェクトになります。
中身を知りたい場合はconsole.logで以下の値を得られます。

MediaQueryList {
media: "(min-width: 896px)",
matches: true
}

検知できるようにイベントリスナーを設定する。

レスポンシブでウィンドウサイズを変更してブレイクポイントを常に検知できるようにMediaQueryList にaddListenerでイベントリスナーを登録することができます。今回はhandle関数を指定しています。

関数内で条件分岐する

handle関数では、MediaQueryList オブジェクトを引数として渡します。
MediaQueryListオブジェクトにはmatchesプロパティがあり、true falseの論理値が取得できるのでそれをもとにif文で条件分岐で処理します。

if (mq.matches) {
    // ウィンドウサイズが896px以下の時の処理
  } else {
    // それ以外の時の処理
  }

ページが読み込まれた時に実行

イベントリスナーと関数内の処理をしても読み込み時には実行されないと困るので、一度関数を実行します。
その際にhandle関数内にmatchMediaで取得したMediaQueryListオブジェクトを引数として渡しておきましょう。

// ページが読み込まれた時に実行
handle(mediaQuery);

複数のメディアクエリを条件分岐したい場合は?

こうなると複数のメディアクエリのブレイクポイントをもとに条件分岐したいと思いますよね。これまでの方法だと1つのメディアクエリだけになります。

複数の場合は以下の方法があります。

if (window.matchMedia('(min-width: 980px)').matches) {
        //処理
    } else if (window.matchMedia('(min-width: 481px)').matches) {
       //処理
    } else if (window.matchMedia('(min-width: 360px)').matches) {
       //処理
    }

だたこの方法だとページが読み込まれた時にしかチェックできません。

複数のメディアクエリで条件分岐させるには?

では、どのように複数のメディアクエリをブレイクポイントして条件分岐させるのかというと以下の方法となります。

function checkMediaQuery(){
   if (window.matchMedia('(min-width: 980px)').matches) {
        //処理
    } else if (window.matchMedia('(min-width: 481px)').matches) {
       //処理
    } else if (window.matchMedia('(min-width: 360px)').matches) {
       //処理
    }
}

//読み込み時とリサイズ時に関数を実行
window.onload = checkMediaQuery;
window.onresize = checkMediaQuery;

if文でメディアクエリ事に条件分岐した処理を関数にして、読み込み時にwindow.onload ウィンドウ幅のサイズが変更された時にwindow.resizeで関数を実行しています。

結局はwindow.resizeを使うことになりましたが、ブレイクポイントの時にしか処理が動くのでCSSのメディアクエリと同じタイミングで何かしたい時はいいかもですね。

まとめ

さて、今回は、window.matchMediaというメソッドがあることを今更知ったのでメモしました。

一応codePenでサンプルを2つ作ってみました。以下、codePenを別タブで開くなりしてウィンドウ幅を変えてみるとブレイクポイントで背景色が変わります。