JavaScriptのmatchMediaメソッドを使ったメディア判定



Webを利用するユーザーの環境は様々で、より良いUI/UXを意識するのであれば、WebデザインだけでなくJavaScriptによるプログラムの実装も、ユーザーの環境に合わせることが求められます。

JavaScriptではmatchMediaメソッドを使うことで、メディアクエリや表示領域のリサイズの判定、hover動作のデバイスの判別、Webブラウザのライトモードとダークモードの判別など、様々なメディア判定が可能となります。

ブラウザの画面の色調はどのモードを設定しているのか、画面幅はどれくらいか、リサイズすることもある、hoverが動作するデバイスかどうかなど、ユーザーの環境を考えると、ユーザーが快適にWebを利用するために表示や動作を調整したり変更する必要があります。

CSSのみで判別して対応できる部分もありますが、JavaScriptでのメディア判定の処理が必要なこともあります。

matchMediaメソッドを利用することで、ユーザーの環境に合わせてプログラムを実行することができます。

matchMediaメソッドの簡単な使い方


まずは、matchMediaメソッドの簡単な使い方について見ていきます。

matchMediaメソッドは、指定されたメディアクエリ文字列のパース結果を、MediaQueryListオブジェクトとして返します。

構文

mql = window.matchMedia(mediaQueryString)


matchMediaメソッドの引数(mediaQueryString)には、メディアクエリやメディア特性を指定します。



例として、ビューポートサイズで判断するメディアクエリでは、以下のようにmatchMediaメソッドを利用します。

JavaScript

/* メディアクエリを指定してMediaQueryList(mql)を作成する */
const mql = window.matchMedia('(min-width: 768px)')

// matchesプロパティでMediaQueryListEventインターフェイスを読み取り条件分岐処理を行う
// 〔論理値(true/false)を返す〕
if (mql.matches) {
  console.log('PC');
} else {
  console.log('SP');
}


Windowインターフェイスに対してmatchMediaメソッドを使ってメディアクエリを指定し、返ってくるMediaQueryListオブジェクトをconst定数(mql)に格納しておきます。
if文の条件分岐にて、MediaQueryListオブジェクト(mql)をmatchesプロパティでチェックして判断して処理を切り分けます。
matchesプロパティはMediaQueryListEventインターフェイスの読み取り専用プロパティで、trueまたはfalseの論理値を返します。trueを返せばPC用の処理、falseを返せばSP用の処理を実行する流れになります。

ここからは、ウィンドウのリサイズやダークモードの判別、hover動作デバイスなど、様々なメディア判定の方法をご紹介します。

メディアクエリと表示領域のリサイズの判定


レスポンシブWebデザインにおいて、ウィンドウをリサイズした時に画面幅に応じてレイアウトを切り替える場合は、リサイズ時のスクリプトの実行が必要になってくるでしょう。

以下はこれまでのresizeイベントを使ったプログラムになります。

JavaScript(これまでのresizeイベントでの処理)

// コールバック関数
const handleChangeMediaQuery = () => {
  if (window.innerWidth >= 768) {
    console.log('PC');
  } else {
    console.log('SP');
  }
};

// 初期化処理
handleChangeMediaQuery();

// コールバック関数をリスナーとして追加
window.addEventListener('resize', handleChangeMediaQuery);


if文の条件分岐でのそれぞれのプログラムはconsole.logでの確認ですが、実際は画面幅に合わせて要素にクラスを追加するなどして、スタイルを変更するなどの対応を行うことでしょう。

ただresizeイベントでプログラムを実行すると、リサイズするたびにJavaScriptの処理が走るので、ブラウザのパフォーマンスの低下ことがあります。クラスの付与くらいなら大した影響はありませんが気になるところです。

今回ご紹介するmatchMediaメソッドとchangeイベントを利用することで、指定したメディアクエリが変更された時だけJavaScriptの処理を走らせることができます。

以下、サンプルコードになります。
メディアクエリを指定してMediaQueryList(mql)を作成し、MediaQueryListオブジェクトの情報をもとにプログラムを実行していきます。

JavaScript

//メディアクエリを指定して MediaQueryList(mql)を作成
const mql = window.matchMedia('(min-width: 768px)');

// コールバック関数
const handleChangeMediaQuery = (event) => {
  if (event.matches) {
    console.log(event);
    console.log(event.matches);
    console.log('PC');
  } else {
    console.log(event);
    console.log(event.matches);
    console.log('SP');
  }
}

// 初期化処理(コールバック関数にMediaQueryListオブジェクトを渡して一度実行)
handleChangeMediaQuery(mql);

// コールバック関数をリスナーとしてMediaQueryList(mql)に追加
mql.addEventListener('change', handleChangeMediaQuery);


window.matchMediaの引数にメディアクエリを指定して、MediaQueryList(mql)をconst定数に格納します。
MediaQueryListオブジェクトの情報をもとに、条件で処理を切り分けるコールバック関数を作成しておきます。コールバックの関数名は「handleChangeMediaQuery」とします。
関数のif文の条件では、MediaQueryListオブジェクトをmatchesプロパティでチェックします。trueを返せばPC用の処理、falseを返せばSP用の処理を実行します。

最初にアクセス時に一度実行する初期化処理として、handleChangeMediaQuery(mql)を実行しています。
そしてaddEventListenerメソッドで、changeイベントが発生したときに、コールバック関数をリスナーとしてMediaQueryListに追加して関数の処理を実行します。

PCとSPそれぞれの処理では、console.logでWebブラウザのデベロッパーツールのコンソールに情報を表示していますが、matchesメソッドでMediaQueryListオブジェクトを確認すると、「matches: true」のようにメディアクエリ(min-width: 768px)にマッチしているかを論理値で確認できます。

以下、Webブラウザのデベロッパーツールのレスポンシブモードでの確認の様子です。
最初のアクセス時のPCの画面幅で、メディアの判定に対してmatchesがtrueとなっていますので、PCとなることがわかります。
そして、画面幅をリサイズして小さくした時に、メディアの判定に対してmatchesがfalseとなり、要素の値が変更されchangeイベントが発行され、コールバック関数が実行されます。
type要素が追加され、changeイベントが発生しているのも確認できます。

matchMediaメソッドとchangeイベントを利用したメディアクエリと表示領域のリサイズの判定



このように、リサイズ時にメディアクエリの判定が変更したときだけ、JavaScriptの処理が走るようにすることができます。

Dark Modeの判別


次はDark Modeの判別について見ていきます。
matchMediaメソッドの使い方は同じで、メディア特製を指定してプログラムを組んでいきます。

以下、サンプルコードになります。

JavaScript

// メディア特性を指定してMediaQueryList(prefersColorScheme)を作成
const prefersColorScheme = window.matchMedia("(prefers-color-scheme: dark)");

const handleChangeMode = (event) => {
  if (event.matches) {
    console.log('Dark Mode');
  } else {
    console.log('Light Mode');
  }
};

// 初期化処理(コールバック関数にMediaQueryListオブジェクトを渡して一度実行)
handleChangeMode(prefersColorScheme);

// コールバック関数をリスナーとしてMediaQueryList(prefersColorScheme)に追加
prefersColorScheme.addEventListener('change', handleChangeMode);


ダークモードではmatchMediaメソッドの引数に、メディア特性「prefers-color-scheme」を指定します。
コールバックの関数名は「handleChangeMode」として、実行結果をコンソールに表示して確認します。
他、初期化処理とaddEventListenerメソッドで、changeイベントが発生したときに、コールバック関数をリスナーとしてMediaQueryListに追加して関数の実行します。

Webブラウザのデベロッパーツールに確認してみますと、まずはアクセス時に現在の設定のLight Modeがコンソールに表示されます。

matchMediaメソッドを使ったライトモードとダークモードの判別



デベロッパーツールでライトモードとダークモードを切り替える場合は、Elementsタブの表示右側のStylesの項目にある色調設定のアイコンから設定が選択できます。
「prefers-color-scheme: dark」を選択するとダークモードに切り替わり、Consoleタブを選択するとDark Modeがコンソールに表示されているのが確認できます。

Webブラウザのデベロッパーツールでのライトモードとダークモードの切り替え

hover動作デバイスの判定


hoverが動作するデバイスかどうかで、JavaScriptの処理を変えることもあるでしょう。
hoverメディア特性には、hoverとany-hoverの2種類がありますが、タブレット端末でマウスやトラックパッド付きのキーボードを接続した場合にも適用される、よりユーザーの環境に合わせることができるany-hoverで判別する方法をご紹介します。

以下、サンプルコードになります。

JavaScript

// メディア特性を指定してMediaQueryList(hasHover)を作成
const hasHover = window.matchMedia("(any-hover: hover)");

const checkHover = (event) => {
  if (event.matches) {
    console.log('hover');
  } else {
    console.log('nothover');
  }
};

// 初期化処理(コールバック関数にMediaQueryListオブジェクトを渡して一度実行)
checkHover(hasHover);

// コールバック関数をリスナーとしてMediaQueryList(hasHover)に追加
hasHover.addEventListener('change', checkHover);


matchMediaメソッドの引数に、メディア特性「any-hover」を指定します。
コールバックの関数名は「checkHover」として、実行結果をコンソールに表示して確認します。
他、初期化処理とaddEventListenerメソッドで、changeイベントが発生したときに、コールバック関数をリスナーとしてMediaQueryListに追加して関数の実行します。

スマートフォンやタブレット端末での実装は、できれば実機で確認できればいいですが、Webブラウザのデベロッパーツールでも確認は可能です。

PCでアクセスではコンソールにはhoverと表示されます。
デベロッパーツールのレスポンシブモードで、画面右上の矢印アイコンから「Add device type」を選択すると、デバイスタイプの項目が表示され、レスポンシブモードでデバイスタイプを変更できるようになります。
Mobileに設定してからブラウザを更新すると、デバイスタイプがモバイルに変更されたのでコンソールにはnothoverと表示されます。

デベロッパーツールのレスポンシブモードでデバイスタイプをMobileに変更する



タブレット端末でマウスやトラックパッド付きのキーボードを接続した場合として、デバイスタイプをMobile (no touch) に変更すると、changeイベントが発生してコールバック関数が実行されますので、変更したタイミングでコンソールにはnothoverと表示されます。

デベロッパーツールのレスポンシブモードでデバイスタイプをMobile (no touch) に変更する



これで、ユーザーの環境に合わせてスクリプトを実装していくことができます。

最後に


CSSのみで判別することもできますが、JavaScriptでのメディア判定の処理が必要なこともありますので、matchMediaメソッドの使い方を知っておくといいでしょう。

あとはメディアの判別に合わせて、実行したいプログラムを書いていってください。