• matchMedia()は画面幅の数値ではなくMedia Queryの一致をJavaScriptで調べる

matchMedia()は画面幅の数値ではなくMedia Queryの一致をJavaScriptで調べる

公開日: 執筆:佐藤

window.matchMedia()は、画面幅の数値を返す関数ではありません。指定したMedia Queryが現在の表示条件に一致するかを調べ、結果を持つMediaQueryListを返します。真偽は、そのmatchesプロパティで確認します。

見た目だけを切り替えるならCSSの@mediaを使います。JavaScriptの処理を同じ条件で切り替える必要がある場合に、matchMedia()を使います。幅の数値そのものが必要な処理とは分けてください。

matchMedia()はMedia Queryを受け取る

CSSOM ViewのmatchMedia()の定義では、matchMedia()はMedia Queryの文字列を受け取り、新しいMediaQueryListを返します。

var layoutQuery = window.matchMedia('(min-width: 768px)');

if (layoutQuery.matches) {
  // 768px以上の表示条件に一致する場合の処理
}

layoutQueryに幅の数値が入るわけではありません。matchesには、指定した条件に一致すればtrue、一致しなければfalseが入ります。条件そのものは、mediaプロパティから文字列として確認できます。

Media Queriesの仕様では、Media Queryはメディア種別とメディア特性を組み合わせ、条件を真または偽として評価します。min-width、max-width、orientationなどを組み合わせられます。

CSSのmedia queryとJavaScriptの判定を分ける

CSSでは、Media Queryに一致したときの表示を@mediaへ書きます。

@media screen and (min-width: 768px) {
  .site-navigation {
    display: block;
  }
}

余白、列数、文字サイズ、表示と非表示など、CSSで表現できる見た目はCSSへ任せます。JavaScriptで同じスタイルを一つずつ書き換える必要はありません。

matchMedia()は、表示条件に応じてJavaScriptの動作を変える場合に使います。たとえば、狭い表示ではボタンで開閉し、広い表示では常に開くナビゲーションの状態管理が該当します。次は仕組みを説明する仮例です。

var layoutQuery = window.matchMedia('(min-width: 768px)');

function updateNavigation(query) {
  var navigation = document.getElementById('site-navigation');

  if (navigation === null) {
    return;
  }

  if (query.matches) {
    navigation.classList.add('is-wide');
  } else {
    navigation.classList.remove('is-wide');
  }
}

updateNavigation(layoutQuery);
layoutQuery.addListener(updateNavigation);

最初のupdateNavigation(layoutQuery)は、ページを開いた時点の状態を反映します。addListener()は、その後でMedia Queryの評価が変わったときに関数を呼び出します。不要になった監視は、同じ関数をremoveListener()へ渡して解除します。

innerWidthは幅を数値で取得する

window.innerWidthは、表示領域の幅をCSSピクセル単位の数値で返します。数値を計算へ使う場合はinnerWidth、Media Queryに一致するかだけを知りたい場合はmatchMedia()という区別です。

手段 得られるもの 主な用途
CSSの@media 条件に一致したときのスタイル 配置、余白、表示方法を変える
matchMedia().matches Media Queryに一致するかという真偽 JavaScriptの動作を切り替える
window.innerWidth 表示領域の幅を示す数値 幅を使った計算をする

matchMedia('(min-width: 768px)')のwidthは、端末の物理的な画面幅ではなく、連続表示媒体では表示領域の幅を対象にします。端末名を推測する条件ではありません。同じ幅でも、利用者がウィンドウを狭めたり、端末の向きを変えたりすれば評価は変わります。

Media Queryの条件を重複させすぎない

CSSとJavaScriptへ別々の境界値を増やすと、片方だけを変更したときに動作がずれます。まず、JavaScriptの切り替えが本当に必要かを確認してください。見た目だけならCSSで完結させます。

JavaScriptにも条件が必要なら、Media Queryの文字列を一か所へまとめ、CSS側で使う境界値と一緒に変更記録へ残します。768という数値だけでなく、その値で何を切り替えるかも書きます。

対象ブラウザーがmatchMedia()、MediaQueryList、addListener()に対応するかも確認が必要です。対応を確認できない環境を含むなら、条件判定がなくても主要な情報と操作を利用できる状態を先に作ります。

一つの切り替え条件から確認する

最初に、画面幅を直接比較しているJavaScriptを一つ選びます。その処理が見た目の変更だけなら、CSSの@mediaへ移せないかを確認します。動作の変更が必要なら、同じ条件をmatchMedia()へ渡し、初期状態と条件変更後の両方を試します。

確認記録には、Media Queryの文字列、切り替える動作、初期化する関数、監視を解除する時点、対象ブラウザーを残します。幅の数値を取ることと、表示条件への一致を調べることを分ければ、何を直すべきかが明確になります。

戻る