JavaScript を前提にしたページを作っていると、「JavaScript が無効な人には何も表示されない真っ白な画面になってしまう」という問題に行き当たります。この場合の受け皿になるのが <noscript> 要素です。この記事では、noscript の基本の書き方から、body 内と head 内で書ける内容の違い、計測タグや代替画像といった実践的な使いどころ、そして CSS の no-js クラスを使う手法との使い分けまでを解説します。中身が表示されないときの原因と、確実な動作確認の手順もあわせて紹介します。
目次
noscript 要素とは
<noscript> は、ブラウザーがスクリプトに対応していないとき、またはスクリプトの実行が無効になっているときだけ、中身を表示する要素です。逆に JavaScript が有効なブラウザーでは、中身は表示されません。専用の属性は持たず、指定できるのは class や id などのグローバル属性だけです。
実装上のポイントとして、JavaScript が有効なときは <noscript> の中身が要素ではなくテキストとして扱われるという仕様があります。中に <img> や <iframe> を書いても、JavaScript が有効な環境ではそれらが要素として解釈されないため、画像や iframe の読み込みも発生しません。無駄な通信を起こさずに代替内容を用意できる、というのが <noscript> の強みです。
また、開始タグと終了タグはどちらも省略できません。<noscript> の中にさらに <noscript> を入れ子にすることもできない点も覚えておいてください。
基本の使い方
もっとも単純な使い方は、body の中にメッセージを書いておくことです。次のコードでは、JavaScript が無効なブラウザーでのみ案内文が表示されます。
<body>
<p>この段落は、JavaScript の有効・無効にかかわらず表示されます。</p>
<!-- JavaScript が無効なときだけ表示される -->
<noscript>
<p>このページの一部の機能は JavaScript を使用しています。ブラウザーの設定で JavaScript を有効にしてください。</p>
</noscript>
</body>
JavaScript が有効なブラウザーで開くと最初の段落だけが表示され、無効にすると案内文も一緒に表示されます。切り替えはページを読み込んだ時点のスクリプトの有効・無効で決まるため、あとから JavaScript で表示を切り替えるようなものではありません。
body 内と head 内で書ける内容の違い
<noscript> はメタデータコンテンツでもフローコンテンツでもあるため、<head> の中にも <body> の中にも置けます。ただし、どこに置くかで中に書ける要素が変わります。
| 置く場所 | 中に書ける内容 | 主な用途 |
|---|---|---|
<head> の中 | <link> / <style> / <meta> を任意の順序で0個以上 | JavaScript 無効時だけ適用する CSS の読み込み |
<body> の中 | フローコンテンツ・記述コンテンツ(見出し、段落、リンク、画像、iframe など) | 案内文の表示、代替コンテンツの表示 |
<head> の中に書けるのは <link>・<style>・<meta> の3つだけです。ここに段落や div を書いても仕様どおりではないので、文章を出したいときは必ず <body> の中に置いてください。
<head>
<meta charset="UTF-8">
<title>サンプルページ</title>
<link rel="stylesheet" href="/css/style.css">
<!-- JavaScript が無効なときだけ読み込まれるスタイル -->
<noscript>
<link rel="stylesheet" href="/css/no-js.css">
<style>
/* JavaScript でしか動かない UI を隠す */
.js-only { display: none; }
</style>
</noscript>
</head>
この書き方なら、JavaScript が有効な環境では no-js.css のリクエストすら発生しません。JavaScript 無効時のためだけのスタイルを、通常時のパフォーマンスを損なわずに用意できます。
実践的な使いどころ
JavaScript 必須のアプリで案内を出す
React や Vue などで作った SPA は、JavaScript が動かないとマウント先の要素が空のままになり、真っ白な画面になります。何も説明がないと「サイトが壊れている」と受け取られてしまうため、原因と対処を伝える案内を <noscript> に置いておきます。
<body>
<noscript>
<div class="noscript-notice">
<h1>JavaScript を有効にしてください</h1>
<p>
当サービスのご利用には JavaScript が必要です。
お使いのブラウザーの設定を確認して、JavaScript を有効にしてから再読み込みしてください。
</p>
<p>
設定方法は<a href="/help/javascript">こちらのヘルプ</a>をご覧ください。
</p>
</div>
</noscript>
<!-- ここにアプリが描画される -->
<div id="root"></div>
<script src="/js/app.js"></script>
</body>
マウント先の <div id="root"> より前に置いておくと、レイアウトを組まなくても案内が画面の先頭に出るので確実です。案内文には「何が必要か」「どうすれば直るか」の2点を必ず含めましょう。
計測タグの noscript 版を設置する
アクセス解析のタグは、JavaScript が動かない環境では計測できません。そこで Google タグマネージャーのように、<noscript> の中に画像や <iframe> を置いてサーバーへのリクエストだけでも発生させる、という手法が使われます。タグマネージャーの公式スニペットは、<body> の開始タグ直後に次の形で設置します。
<body>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
先ほど触れたとおり、JavaScript が有効な環境ではこの <iframe> は要素として解釈されないので読み込まれません。通常の閲覧者には一切の負荷をかけずに、JavaScript 無効時のフォールバックだけを用意できるわけです。
JavaScript で描画している領域の代替を出す
画像の遅延読み込みをライブラリで行っている場合、JavaScript が無効だと data-src が読み込まれず画像が表示されません。この場合も <noscript> に通常の <img> を用意しておけば、代わりに表示されます。
<!-- JavaScript のライブラリが data-src を src に差し替える --> <img class="lazy" data-src="/images/photo.jpg" alt="海辺の風景" width="800" height="600"> <!-- JavaScript が無効なときの代替 --> <noscript> <img src="/images/photo.jpg" alt="海辺の風景" width="800" height="600"> </noscript>
ただし、遅延読み込みは <img loading="lazy"> でブラウザー標準の機能として利用できます。新しく作るページであれば、JavaScript のライブラリを使わずに loading 属性で済ませるほうが、この代替コード自体が不要になります。同じ考え方は、埋め込み地図やグラフのように JavaScript で描画している領域にも応用でき、静的な画像やテキストによる説明を <noscript> に置いておくと親切です。
CSS の no-js クラスによる出し分けとの違い
<noscript> と似た目的でよく使われるのが、<html> に no-js クラスをあらかじめ付けておき、JavaScript が動いたら外す、という手法です。クラスの有無を CSS のセレクターで拾って表示を切り替えます。
<!DOCTYPE html>
<html lang="ja" class="no-js">
<head>
<meta charset="UTF-8">
<!-- CSS より前に置いてクラスを外す(表示のちらつきを防ぐ) -->
<script>
document.documentElement.classList.remove('no-js');
</script>
<link rel="stylesheet" href="/css/style.css">
</head>
/* JavaScript が必要な UI は、無効なときに隠す */
.no-js .js-only {
display: none;
}
/* 代替表示は通常は隠しておき、JavaScript が無効なときだけ出す */
.fallback {
display: none;
}
.no-js .fallback {
display: block;
}
この手法の利点は、ページのどこにある要素でも一括で出し分けられることです。「JavaScript が無効なときはこのボタンを隠す」といった、既存のマークアップに手を入れずに済む制御が得意です。一方で <noscript> は、そこに書いた内容だけを追加で表示するものなので、隠す用途には向きません。
| 観点 | <noscript> | no-js クラス |
|---|---|---|
| できること | 代替内容を追加で表示する | 既存要素の表示・非表示を切り替える |
| CSS が無効なとき | そのまま表示される | 切り替えが効かない |
| 中の画像・iframe | JavaScript 有効時は読み込まれない | display: none でも読み込まれる |
| 準備するもの | 要素を書くだけ | head 内のスクリプトと CSS の記述 |
| 向いている場面 | 案内文、計測タグ、代替画像 | UI 全体の見た目の調整 |
実務では、この2つは競合するものではなく組み合わせて使います。「JavaScript が必要なボタンを隠す」のは no-js クラス、「代わりの案内文やリンクを出す」のは <noscript>、と役割で分けるのが分かりやすい整理です。
noscript の中身が表示されないときに確認すること
JavaScript は有効だがエラーで止まっている
もっとも誤解が多いのがこのケースです。<noscript> が判定しているのはスクリプトが有効かどうかだけで、スクリプトが正しく動いたかどうかは見ていません。読み込んだ JavaScript が構文エラーや実行時エラーで途中で止まっても、ブラウザーにとってスクリプトは有効なままなので、<noscript> の中身は表示されません。
つまり「JavaScript が壊れたときの保険」としては機能しません。スクリプトの失敗に備えるなら、try...catch や window.onerror でエラーを捕まえて、自分でメッセージを表示する必要があります。読み込み自体の失敗であれば、<script> タグの error イベントで検知できます。
// スクリプトが動いたうえでの失敗は noscript では拾えない
try {
initApp();
} catch (error) {
// 自前でエラー用の表示を出す
document.getElementById('root').textContent =
'読み込みに失敗しました。ページを再読み込みしてください。';
console.error(error);
}
拡張機能がスクリプトだけをブロックしている
広告ブロッカーやトラッキング防止系の拡張機能は、ブラウザーの JavaScript 設定そのものは有効なまま、特定のスクリプトの読み込みだけを遮断することがあります。この状態ではスクリプトは有効と判定されるので、やはり <noscript> の中身は出てきません。計測タグが動かないのに <noscript> の代替も出ない、という現象はこれが原因であることが多いです。
拡張機能によっては <noscript> の中の <iframe> の通信先までブロックするため、代替側も届かないことがあります。ここは制作側で完全に対処できる範囲ではないので、切り分けのために拡張機能をすべて無効にしたシークレットウィンドウで確認してみてください。
head 内に書ける要素以外を入れている
前述のとおり、<head> の中の <noscript> に書けるのは <link>・<style>・<meta> だけです。ここに段落や div を書くと、ブラウザーのパース処理によって想定外の位置に押し出され、意図した表示になりません。文章やリンクを表示したいときは <body> に移してください。
あわせて、<noscript> を入れ子にしていないか、終了タグを書き忘れていないかも確認しましょう。終了タグは省略できないため、閉じ忘れると以降のマークアップがすべて <noscript> の中身として扱われ、JavaScript が有効な環境でページの大部分が消えたように見えます。
動作確認の手順
Chrome では、開発者ツールを開いた状態で Ctrl(Mac は Command)+ Shift + P でコマンドメニューを開き、「Disable JavaScript」を実行すると JavaScript を無効にできます。実行したらページを再読み込みしてください。<noscript> の表示はページを読み込んだ時点で決まるため、無効にしただけでは切り替わりません。
この設定は開発者ツールを開いている間だけ有効で、閉じると元に戻ります。ブラウザーの設定画面(Chrome の場合は「プライバシーとセキュリティ」内のサイトの設定)から JavaScript をブロックする方法でも確認できますが、戻し忘れると他のサイトの閲覧に支障が出るので、開発者ツールから切り替えるほうが安全です。なお、ページのソースを表示しただけでは <noscript> は HTML 上に常に存在するため、確認の役には立ちません。
まとめ
<noscript> は、ブラウザーがスクリプトに未対応、またはスクリプトが無効なときだけ中身を表示する要素です。<body> の中では見出しや段落、リンク、画像といったフローコンテンツを自由に書けますが、<head> の中では <link>・<style>・<meta> の3つに限られます。JavaScript が有効なときは中身がテキストとして扱われ、画像や iframe の読み込みも起きないため、通常の閲覧者に負荷をかけずに代替内容を用意できます。JavaScript 必須のアプリでの案内文、計測タグの代替、遅延読み込み画像のフォールバックが代表的な使い道です。要素の表示・非表示を広く制御したいときは no-js クラスによる手法と組み合わせるとよいでしょう。判定の対象はあくまでスクリプトが有効かどうかであり、スクリプトがエラーで止まった場合や拡張機能にブロックされた場合には表示されない点だけ、勘違いしないよう注意してください。