CSS の scripting メディア特性を使うことで、ウェブブラウザをはじめとする、ユーザエージェントの JS のサポート状況に応じて、スタイルを出し分けることができます。

この記事では、この scripting メディア特性の基本説明に加え、実例を挙げながら利用シーンを考えていきます。

scripting メディア特性は、W3C の仕様では「Media Queries Level 5」に属しており、草案(Working Draft)段階のため、今後、実装方法や機能に変更が発生する可能性があります。

また、この scripting メディア特性は、主要なブラウザでサポートされていますが、Safari でのサポートは 17.0 からと比較的最近なので、こちらも注意が必要です。

scripting メディア特性の基本

見出し「scripting メディア特性の基本」

scripting メディア特性には、noneinitial-onlyenabled の値を指定できます。

以下のコードのように、none は JS が無効なときのスタイル、enabled は JS が有効なときのスタイルを指定できます。

none と enabled を指定する例
/* JS が無効なときのスタイル */
@media (scripting: none) {
  .foo {
    display: block;
  }
}

/* JS が有効なときのスタイル */
@media (scripting: enabled) {
  .bar {
    display: block;
  }
}

none の判定は、ユーザが明示的に JS を無効化した場合のみならず、通信速度が極端に遅いときのような外的要因によって、ユーザエージェント側で自動的に JS が無効に切り替わるケースも考えられるかもしれません(可能性は極めて低いですが)。

例えば、Android Chrome では、2018 年に「データセーバ」がオンの状態で、2G 以下のネットワークを使用しているときに、自動的に JS が無効になる機能がデフォルト設定になりました1。ただ、Chrome のバージョン 100 で「ライトモード(かつてのデータセーバ)」が廃止されたので2、今ではこの機能もなくなっているのかもしれません(どうなんでしょう?)。

initial-only は、W3C の仕様ではドキュメントを読み込んだときにだけ JS が有効になる環境が該当するとあります。例として、印刷されたページや、プロキシサーバを介してほぼ静的なページが配信されるケース(JS が制限されたケース)が想定されているようです。

現時点では、initial-only を使用する場面はあまり考えられません。


以下は、何の面白みもないデモですが、ユーザエージェントの JS が利用できる状況に応じてランプが点灯します。通常は enabled が点灯していると思われますが、ブラウザの設定などを変更して、JS を無効にすると none が点灯します。

scripting メディア特性に非対応の環境では、どのランプも点灯しません。

Live Demo
  • none
  • initial-only
  • enabled

ブラウザで JS を無効にする方法はいくつかありますが、デベロッパーツールが使用できる状況では、それぞれ以下のとおりです。

Google Chrome / Microsoft Edge で JS を無効にする設定

デベロッパーツールを開いて「設定 > (基本)設定 > デバッガ」の「JavaScript を無効にする」のチェックボックスを選択します。

Google Chrome のデベロッパーツールで「JavaScript を無効にする」のチェックボックスを選択している状態のスクリーンショット

もしくは、Command + Shift + P キーでコマンドパネルを開いて、javascriptjs とタイピングすると「JavaScript を無効にする」の項目が表示されます。

Google Chrome デベロッパーツールのコマンドパネルで「javascript」と入力している状態のスクリーンショット

Firefox で JS を無効にする設定

デベロッパーツールを開いて「設定 > 詳細設定」の「JavaScript を無効化」のチェックボックスを選択します。

Firefox のデベロッパーツールで「JavaScript を無効化」のチェックボックスを選択している状態のスクリーンショット

Safari で JS を無効にする設定

メニューバーの「開発」から「JavaScript を無効にする」を選択します。

Safari のメニューバーで「JavaScript を無効にする」を選択している状態のスクリーンショット

「開発」メニューが表示されていない場合には、メニューバーの「Safari」から「環境設定」を開いて、「詳細」タブから「メニューバーに開発メニューを表示」を選択します。

ここからは、実例を挙げながら、scripting メディア特性の利用シーンを考えてみます。

例1: ローディング画面

見出し「例1: ローディング画面」

まず、ローディングイメージやプログレスバー、ローディングスピナーなどの、リソースの読み込みを待機している状態を表現する画面がページ全体を覆っている状況を考えてみます。

これらのローディング画面はリソースの読み込みが完了すると非表示になりますが、JS で制御されている場合、無効の状況ではいつまでもローディング画面が消えません。

このケースで scripting メディア特性を使用するには、デフォルトでローディング画面を非表示にして、scripting: enabled で表示するのがよいでしょう。

ローディング画面に `scripting` メディア特性を使用する図
JS が無効なときにはローディング画面を非表示にし、有効なときに表示する
ローディング画面に scripting メディア特性を使用する例
/* デフォルトは非表示 */
.loading {
  display: none;
}

/* JS が有効なときに表示 */
@media (scripting: enabled) {
  .loading {
    display: block;
  }
}

JS で style プロパティを指定しても同じことが実現できますが、CSS で指定することにより、ローディング画面を表示するまでの遅延を少なくすることができます。

次に、いくつかのステップに分かれて進んでいくような UI で、通常のリンク遷移ではなく、JS のクリックイベントをきっかけに、動的にステップが切り替わるケースを考えていきます。

こちらは先ほどの例とは逆に、デフォルトでは次のステップを表示しておき、scripting: enabled で非表示にするのがよいでしょう。

JS でステップが切り替わる UI に `scripting` メディア特性を使用する図
JS が無効なときには次のステップを表示し、有効なときに非表示にする
段階的開示の UI に scripting メディア特性を使用する例
/* デフォルトは表示 */
.step2 { 
  /* ... */
}

/* JS が有効なときに非表示 */
@media (scripting: enabled) {
  .step2 {
    display: none;
  }
}

ただ、JS が有効であったとしても、Safari 16.x のように scripting メディア特性がサポートされていない環境では、JS 無効時と同じ見え方になります。

レイアウトシフトに注意する必要はありますが、このようなケースでは JS 側でもスタイルを指定するのが無難かもしれません。

JS 側でスタイルを指定する例
const isSupported = window.matchMedia('(scripting: enabled)').matches;

if (!isSupported) {
  const step2 = document.querySelector('.step2');
  step2 && step2.style.display = 'none';
}

例3: サードパーティ製のウィジェット

見出し「例3: サードパーティ製のウィジェット」

SNS のタイムラインなどを表示する、サードパーティ製のウィジェットが JS で生成されるケースを考えてみます。

ウィジェットの外側に、見出しなどの静的な要素が含まれていることが一般的ですが、この場合には scripting: none を使用して、見出しを含めたエリアごと非表示にする方法が考えられます。

サードパーティ製のウィジェットに `scripting` メディア特性を使用する図
JS が有効なときにそのまま表示し、無効なときにエリアごと非表示にする
サードバーティ製のウィジェットに scripting メディア特性を使用する例
<div class="widget">
  <h3>SNS</h3>
  <!-- 埋め込みコード -->
  <iframe src="...">
</div>

<style>
/* JS が無効なときに非表示 */
@media (scripting: none) {
  .widget {
    display: none;
  }
}
</style>

ただ、このケースでは、scripting メディア特性を使うのではなく、<noscript> 要素で補足説明を表示したほうが適切かもしれません。

サードパーティ製のウィジェットに `<noscript>` 要素を使用して補足説明を表示している図
<noscript> 要素で補足説明する例
<div class="widget">
  <h3>SNS</h3>
  <!-- 埋め込みコード -->
  <iframe src="...">

  <noscript>
    <p>このコンテンツは JavaScript を有効にする必要があります。</p>
  </noscript>
</div>

全面的にクライアントサイド JavaScript が前提となるサイトでは、JS を無効にするとコンテンツが何も表示されなくなります。

ここでは scripting メディア特性を使用するのではなく、HTML の <noscript> 要素を使用して、コンテンツが表示されない理由を説明をしたほうがよいでしょう。

<noscript> 要素で補足説明する例
<div id="app"></div>
<noscript>
  <p>このウェブサイトを閲覧するには JavaScript を有効にする必要があります。</p>
</noscript>

このように、JS が無効なときに代替コンテンツが必要になる場面では、<noscript> 要素を使用するのが適切だと考えられます。

この記事では、実例を取り上げながら scripting メディア特性の使用方法を説明しました。

JS が無効になるケースはかなり限られているとはいえ3、主要なコンテンツやナビゲーションについては、最低限の情報を取得できるように対応をしておくのがよいかもしれません。

ネットワークの高速化やブラウザの進化により、JS を使用したリッチな表現や機能が増える一方で、モバイルユーザが大多数になっていることや、ウェブサステナビリティの観点から、データ通信量や消費電力の少ないサイトが求められていることも事実です。

また例えば、電力需給が逼迫している状況や、大きな災害に被災した状況でインターネットを利用する場面において、JS を無効にすることで通信量の抑制やバッテリーを長持ちさせることにつながるので、そのような側面がもう少し議論されてもいいのかもしれないと感じています。

もちろん JS が不要だと主張したいわけではないですが、前回の記事「HTML Web Components とは何か」でも触れた Progressive Enhancement な思想をベースに、改めて考えてきたいです。

本記事の作成にあたり、以下のウェブページを参考にしました。

脚注

  1. Feature: Intervention: Disable scripts for Data Saver users on slow connections | Chrome Platform Status

  2. Sunsetting Chrome Lite mode in M100 and older |Google Chrome Community

  3. JS 無効に関する包括的な調査データは見つかりませんでしたが、WebAIM による「Screen Reader User Survey #9 Results(2021)」では、スクリーンリーダーを利用するユーザが、JS を無効にしている割合は 0.6% でした。