- JavaScript
javascript:void(0)とは|意味・#との違いとCSPエラーの直し方
結論
javascript:void(0) は「リンクを押しても、どこにも移動しない」ようにする書き方です。void 演算子はどんな式を渡しても undefined を返すため、ブラウザは何も表示を変えずにその場にとどまります。今は、ページを移動しないボタンには <button type="button"> を使うのが基本です。
この記事でわかること
- void(0) の意味と、void 演算子の実行結果
- href="javascript:void(0)"・href="#"・button の違い(Chromium で実測)
- CSP と React 19 でブロックされたときのエラー原文と直し方
リンクをクリックすると、まず click の処理が動き、preventDefault() されていなければ href の URL へ移動します。href が javascript: のときだけ、ブラウザは移動の代わりに次の順で処理します。javascript:void(0) は、最後に「移動しない」へ進むための書き方です。
flowchart TD
A[javascript: を押す] --> K{CSPが許す?}
K -->|いいえ| E[エラー]
K -->|はい| R{文字列?}
R -->|はい| X[ページ置換]
R -->|いいえ| S[移動しない]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| javascript:void(0) とは | 押しても移動しないリンクにするための書き方 | javascript:void(0)とは |
| void(0) の意味 | 0 を評価して undefined を返す。0 に意味は無い | void演算子とは |
| href="#" との違い | # はページ先頭へ戻り、URL と履歴が変わる | 3通りの違い(実測) |
| void(0) はエラーか | エラーではない。サイトの作りの一部 | 表示されて動かないとき |
| リンクが反応しない(閲覧者) | JavaScript の許可・拡張機能・再読み込みを確かめる | 表示されて動かないとき |
| CSP でブロックされた | addEventListener と button に書き換える | CSPでブロックされるエラー |
| React で使えない | React 19 は href を書き換えてエラーにする | Reactでのエラー |
| 今の推奨の書き方 | 動作は button、移動はちゃんとした URL の a | 今の推奨の書き方 |
確認環境:Ubuntu 24.04.5 LTS の上で、void 演算子の結果は Node.js 22.23.4(V8 12.4)で実行しました。比較用のページは Python 3.13.18 の http.server を自作のハンドラーで 127.0.0.1 に起動し、CSP(Content-Security-Policy)のヘッダーをページごとに変えて返しています。ブラウザの挙動は Chromium 153.0.8010.12(Playwright 1.63.0 でヘッドレス起動・日本語)で、クリック・Tab・Enter・Space・Ctrl+クリック・中クリックを送り、スクロール位置・URL・履歴の数・アクセシビリティツリー(ariaSnapshot と DevTools Protocol)・コンソールの文言を記録しました。React は 19.2.8(react-dom 19.2.8)を esbuild 0.28.2 で開発用と本番用にまとめ、同じ Chromium で動かしています。void 演算子と javascript: URL の説明は MDN、React の方針は React 公式ブログ、検索での扱いは Google 検索セントラル、閲覧者向けの設定は Google のヘルプで確かめました。Chrome の画面下に出るステータス表示は、ヘッドレスでは見えないため実測していません。図は mermaid で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「javascript:void(0)とは|意味・#との違いとCSPエラーの直し方」
javascript:void(0)とは(意味を一言で)
この節では、javascript:void(0) が何をする書き方なのかと、3つの部品の意味が分かります。
javascript:void(0) は、a タグの href に書いて「クリックしてもページを移動しない」リンクを作るための書き方です。 クリックしたときの処理は onclick や addEventListener に書き、href には「何もしない」を置いておく、という使い方をされてきました。
<a href="javascript:void(0)" onclick="openMenu()">メニュー</a>
javascript:
URL の種類(スキーム)。ブラウザは移動する代わりに、後ろに書いたコードを実行する。
http: や mailto: の仲間
void
JavaScript の演算子。後ろの式を評価して、結果を捨て、undefined を返す。
関数ではない
(0)
評価される式。何でもよく、短くて副作用が無いので 0 が慣例になった。
void 0 と同じ
MDN は、javascript: URL を実行した結果が文字列のときは、その文字列でページの中身を置き換え、文字列でなければコードを実行するだけで移動しない、と説明しています。void(0) は「結果を必ず undefined にする」ことで、ページを移動させない(置き換えない)ようにしています。
リンクにマウスを乗せると、ブラウザは画面の下に href の値を表示します。このため、閲覧者は「javascript:void(0)」という文字を目にし、これを検索することになります。表示されること自体はエラーではありません。
void演算子とは(void 0・void(0)の実行結果)
この節では、void 演算子の動きを、Node.js で実行した結果で確かめられます。
void は「後ろの式を評価して、undefined を返す」単項演算子です。 MDN は「与えられた式 (expression) を評価し、undefined を返します」と説明しています。手元で実行した結果です。
$ node void.js
void 0 → undefined
void(0) → undefined
void 1 → undefined
void "abc" → undefined
void (1 + 1) → undefined
typeof void 0 → "undefined"
void 0 === undefined → true
void 2 === "2" → false
void (2 === "2") → undefined
void n++ のあとの n → 1
() => arr.push(1) の戻り値 → 1
() => void arr.push(1) の戻り値 → undefined
void function(){}() で即時実行されました
void だけ(式なし) → "SyntaxError: Unexpected end of input"
1中身は何でも undefined
0・1・"abc"・計算式のどれを渡しても結果は undefined。0 を使うのは短いからで、特別な意味はない。
2式は実行される
void n++ のあと n は 1 になった。捨てるのは結果だけで、副作用(関数の呼び出しなど)は起きる。
3括弧は関数呼び出しではない
void(0) の括弧は式をまとめているだけ。void 2 === "2" は (void 2) === "2" と読まれ false になる。
void が今も使われる場面(アロー関数・即時実行関数)
MDN は、アロー関数の戻り値を使わないことをはっきりさせる書き方として () => void doSomething() を挙げています。上の実行結果のとおり、arr.push(1) は新しい長さ 1 を返しますが、void を付けると undefined になります。
// 戻り値を返さないことを明示する
button.onclick = () => void doSomething();
// 即時実行関数(IIFE)を void で書く
void function () {
console.log("実行されました");
}();
アロー関数をそのまま void の後ろに書いて呼ぶと構文エラーになりました。括弧で囲むと動きます。
void () => {}() → SyntaxError: Malformed arrow function parameter list
void (() => {...})() → void (() => {})() は動きました
javascript: URLの仕組み(戻り値が文字列だとページが置き換わる)
この節では、なぜ href に void を付けるのかが、置き換わる実例で分かります。
javascript: URL の結果が文字列だと、ページ全体がその文字列に置き換わります。 MDN は「関数呼び出しで終わるなら void を前に付ける」ことを勧めています。手元で、文字列を返す関数を2通りで呼びました。
<script>
function getLabel() { return "保存しました"; }
</script>
<a id="s1" href="javascript:getLabel()">戻り値が文字列の関数を呼ぶ</a>
<a id="s2" href="javascript:void getLabel()">void を付けて呼ぶ</a>
| href | クリック後の URL | クリック後のページ |
|---|---|---|
javascript:getLabel() |
変わらない(/string.html) | <html><head></head><body>保存しました</body></html> だけになった |
javascript:void getLabel() |
変わらない | 元のページのまま(関数は実行された) |
javascript:void(0) |
変わらない | 元のページのまま |
URL はそのままで中身だけが「保存しました」に変わるため、原因に気づきにくい不具合になります。 void(0) や void 関数() は、この置き換えを確実に防ぐための書き方です。
なぜvoid(0)が使われてきたのか(undefinedの歴史)
この節では、undefined と書かずに void(0) と書いてきた理由と、今はどうなっているかが分かります。
以前の JavaScript(ECMAScript 3 まで)は、グローバルの undefined を書き換えられたため、「確実に undefined を得る」方法として void 0 が使われました。 ECMAScript 5 からグローバルの undefined は書き換えできなくなっています。手元の Node.js で確かめた結果です。
Object.getOwnPropertyDescriptor(globalThis, "undefined")
→ { value: undefined, writable: false, enumerable: false, configurable: false }
グローバル(非strict): var undefined = 1; undefined → undefined (無視された)
strict モードで undefined = 1 → TypeError: Cannot assign to read only property 'undefined' of object '#<Object>'
関数の中: var undefined = 1; return undefined → 1 (関数の中の変数としては作れてしまう)
関数の中で const undefined = 42 のとき [undefined, void 0] → [ 42, undefined ]
- グローバルでは上書きできない:writable: false で、strict モードなら TypeError になります。
- 関数の中では同じ名前の変数を作れる:そのときも
void 0は必ず本物の undefined を返しました。圧縮ツール(minifier)が undefined をvoid 0に置き換えるのは、短くて確実だからです。 - href での使い方は別の話:href の javascript:void(0) は、上の「ページの置き換え」を防ぎつつ移動を止める目的で広まりました。
href="javascript:void(0)"・href="#"・buttonの3通りの違い(Chromiumで実測)
この節では、よく比べられる3つの書き方(と2つの変形)で、クリック後に何が変わるのかが実測で分かります。
href="#" は「ページの先頭(#)へ移動するリンク」なので、スクロールが先頭に戻り、URL の末尾に # が付き、履歴が1つ増えます。 上部に固定したメニューに5つの部品を並べ、2000px スクロールしてからクリックしました。どれもクリックの処理(addEventListener)は1回ずつ動いています。
<a id="v" href="javascript:void(0)">メニューA</a>
<a id="h" href="#">メニューB</a>
<a id="hp" href="#">メニューC</a> <!-- click で preventDefault() する -->
<button id="b" type="button">メニューD</button>
<a id="n">メニューE</a> <!-- href なし -->
| 書き方 | スクロール位置 | URL | 履歴(history.length) | hashchange |
|---|---|---|---|---|
| href="javascript:void(0)" | 2000 のまま | 変わらない | 増えない | 0回 |
| href="#" | 2000 → 0(先頭へ) | 末尾に # が付く | 1つ増える | 1回 |
| href="#"+preventDefault() | 2000 のまま | 変わらない | 増えない | 0回 |
| button type="button" | 2000 のまま | 変わらない | 増えない | 0回 |
| a(href なし) | 2000 のまま | 変わらない | 増えない | 0回 |
href="#" をクリックしたあとにブラウザの「戻る」を押すと、URL の # が消えてスクロール位置は 2000 に戻りました。閲覧者から見ると「戻るを押しても前のページに戻らない」状態になります。
新しいタブ・JavaScript無効・baseタグでの違い
普通のクリック以外の操作でも比べました。
| 操作 | javascript:void(0) | href="#" | button |
|---|---|---|---|
| Ctrl+クリック・中クリック | タブは開かない(1枚のまま) | 同じページ(…#)のタブが2枚開いた | 新しいタブの操作は無い |
| JavaScript を無効にしてクリック | 何も起きない | URL に # が付き先頭へ | 何も起きない |
<base href="/other/"> のページでクリック |
移動しない | /other/# へ移動した(別のページ) | 移動しない |
| マウスカーソル(CSS の cursor) | pointer(指の形) | pointer | default(矢印) |
| document.links に入るか | 入る | 入る | 入らない |
- base タグがあると、href="#" は「base の URL の #」になります。 手元では別のページ /other/ へ移動しました。void(0) が好まれた理由の1つです。
- href の無い a は、カーソルが auto(文字の上では I の形)になり、リンクとして扱われません。 「href に何か書かないとリンクにならない」ため、何もしない値として void(0) が置かれてきました。
- button のカーソルを指の形にしたいときは、CSS で
cursor: pointerを指定します。
キーボード操作とアクセシビリティの違い
この節では、Tab・Enter・Space で操作したときと、スクリーンリーダーに伝わる役割(ロール)の違いが分かります。
button は Enter でも Space でも押せますが、リンク(a)は Enter でしか動きません。 各部品にフォーカスを当ててキーを押した結果です。
| 書き方 | Tab で止まる | Enter | Space |
|---|---|---|---|
| href="javascript:void(0)" | 止まる | クリックの処理が動く | 動かない(ページが 2000→2630 にスクロール) |
| href="#" | 止まる | 動く(先頭へ移動もする) | 動かない(ページがスクロール) |
| button type="button" | 止まる | 動く | 動く |
| a(href なし) | 止まらない | フォーカスできず押せない | 同左 |
Tab を5回押したときのフォーカスの順は v → h → hp → b → BODY で、href の無い a は飛ばされました。Playwright の ariaSnapshot で見たアクセシビリティツリーです。
- navigation:
- link "メニューA":
- /url: javascript:void(0)
- link "メニューB":
- /url: "#"
- link "メニューC":
- /url: "#"
- button "メニューD"
- text: メニューE
link(リンク)と伝わる
javascript:void(0)・href="#"
「どこかへ移動する」と受け取られる
Space では押せない
button(ボタン)と伝わる
button type="button"
「この場で何かが起きる」と受け取られる
Enter・Space の両方で押せる
メニューを開く・モーダルを出すといった「その場の操作」をリンクとして伝えると、スクリーンリーダーの利用者は移動先があると受け取ります。 操作には button、移動には URL を持つ a、と役割で分けると、キー操作もロールも自然に合います。
CSPでjavascript:void(0)がブロックされるエラー(原文)
この節では、CSP(Content-Security-Policy)を入れたサイトで javascript:void(0) が動かなくなるエラーの原文と、ポリシーごとの結果が分かります。
CSP の script-src に 'unsafe-inline' が無いと、javascript: URL へのクリックはブロックされます。 MDN も「javascript: のナビゲーションは CSP、特に script-src でブロックされることがある」としています。Content-Security-Policy: script-src 'self' を返すページで、void(0) のリンクをクリックしたときの Chromium のコンソールです。
Running the JavaScript URL violates the following Content Security Policy directive 'script-src 'self''. Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present. The action has been blocked.
onclick 属性も同じ理由で止まります。
Executing inline event handler violates the following Content Security Policy directive 'script-src 'self''. Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present. The action has been blocked.
同じ4つの部品を、ポリシーを変えて試しました(javascript: で処理は href="javascript:window.ran=1;void(0)")。
| 返したポリシー | void(0) のリンク | onclick 属性 | javascript: で処理 | addEventListener の button |
|---|---|---|---|---|
script-src 'self' |
ブロック(エラー) | ブロック | ブロック・処理されない | 動く |
script-src 'self' 'unsafe-inline' |
動く | 動く | 動く | 動く |
| 同じ内容を Report-Only で | 動く(記録だけ) | 動く(記録だけ) | 動く(記録だけ) | 動く |
'unsafe-hashes'+void(0) の sha256 |
動く(エラーなし) | ブロック | ブロック | 動く |
require-trusted-types-for 'script' |
ブロック | 動く | ブロック | 動く |
Report-Only(Content-Security-Policy-Report-Only)では、同じ文の末尾が「The policy is report-only, so the violation has been logged but no further action has been taken.」になり、コンソールの種類は error ではなく info でした。Trusted Types を求めるポリシーでは、次の別の文言が出ました。
This document requires 'TrustedScript' assignment. Navigating to a javascript:-URL is equivalent to a 'TrustedScript' assignment. The action has been blocked.
- 'unsafe-inline' を足すのは、CSP の効果を大きく下げます。 MDN も、インラインのスクリプトをすべて許すのは危険で、nonce や hash を勧めるとしています。
- 手元の Chromium 153 では、
'unsafe-hashes'と「javascript:void(0)」という文字列全体の sha256 を並べると、その1つの URL だけが動きました。ただし、書き換えられるなら addEventListener に移すのが MDN の勧める方法です。 - いちばん確実な直し方は、href の javascript: と onclick 属性をやめ、外部の .js から addEventListener で処理を付けることです。 上の表のとおり、どのポリシーでも動きました。
CSP の入れ方は関連記事「CSP設定(Content-Security-Policy)|nginx段階導入」で扱っています。
Reactでjavascript: URLがブロックされるエラー(React has blocked…)
この節では、React で href に javascript:void(0) を書いたときに何が起きるのかが、React 19 の実物で分かります。
React 19 は、href の javascript: URL を、エラーを投げるだけの URL に書き換えます。 次のコンポーネントを開発用・本番用の両方で動かしました。
function App() {
return (
<nav>
<a href="javascript:void(0)" onClick={() => openMenu()}>void(0) のリンク</a>
<a href="#" onClick={(e) => { e.preventDefault(); openMenu(); }}>preventDefault</a>
<button type="button" onClick={() => openMenu()}>button</button>
</nav>
);
}
描画された DOM の href と、クリックしたときのエラーです(開発用・本番用とも同じでした)。
href in DOM = javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')
(クリック後、捕まえられなかった例外)
Error: React has blocked a javascript: URL as a security precaution.
サーバー側の描画(renderToString)でも、同じ書き換えが入りました。
<a href="javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')">link</a>
- onClick の処理は3つとも1回ずつ動きました。 そのあとで href の「エラーを投げる URL」が実行され、コンソールに例外が出ます。画面が動いていても、エラー監視ツールには毎回このエラーが記録されます。
- React 16.9 の公式ブログは、javascript: URL を「サニタイズされていない値を入れると簡単にセキュリティホールになる攻撃面」とし、16.9 では警告を出し、将来のメジャー版でエラーにすると予告していました。React 19 では上のとおりブロックされます。
- React の直し方は、href をやめて
<button type="button" onClick={…}>にすることです。移動が必要なら、本物の URL を href に入れます。
React のイベントの書き方は関連記事「React onClickに引数を渡す書き方とイベントハンドラ早見表」で扱っています。
javascript:void(0)を使わない今の推奨の書き方(buttonとpreventDefault)
この節では、javascript:void(0) の代わりに何を書けばよいかが、用途別のコードで分かります。
「その場で何かが起きる」なら button、「別のページや場所へ移動する」なら本物の URL を持つ a、が基本です。 MDN も javascript: 疑似プロトコルについて「積極的に使用するべきではない」としています。
メニューを開く・モーダルを出す
<a href="javascript:void(0)" onclick="openMenu()">。CSP と React でブロックされ、Space で押せず、リンクとして読み上げられる<button type="button"> と addEventListener。Enter・Space で押せ、ボタンとして伝わる見た目をリンク風にしたいなら CSS で整える
JavaScript があれば画面内で開き、無ければ別ページへ
href="#" のまま処理を書く。先頭へ飛び、履歴が増え、base があると別ページへ移動するpreventDefault() してから画面内で開く新しいタブで開く・検索に拾われる、が両立する
button で書く(その場の操作)
<button type="button" class="link-like" id="menu-btn"
aria-expanded="false" aria-controls="menu">メニュー</button>
<nav id="menu" hidden>…</nav>
<script src="/menu.js" defer></script>
// menu.js(外部ファイルなので CSP の script-src 'self' でも動く)
const btn = document.getElementById("menu-btn");
const menu = document.getElementById("menu");
btn.addEventListener("click", () => {
const open = btn.getAttribute("aria-expanded") === "true";
btn.setAttribute("aria-expanded", String(!open));
menu.hidden = open;
});
/* リンクのように見せる */
.link-like {
background: none;
border: 0;
padding: 0;
color: inherit;
text-decoration: underline;
cursor: pointer;
font: inherit;
}
button を form の中に置くときは、type="button" を必ず書きます。書かないと既定の submit になり、フォームが送信されます。type の違いは関連記事「HTML button typeの使い方 submit・resetの違い」で扱っています。
a と preventDefault で書く(移動先がある操作)
<a href="/help/shipping" id="help-link">送料について</a>
document.getElementById("help-link").addEventListener("click", (e) => {
if (e.ctrlKey || e.metaKey || e.shiftKey || e.button !== 0) return; // 新しいタブ等はそのまま
e.preventDefault(); // ページ移動を止める
openHelpModal("/help/shipping");
});
上の実測でも、href="#" に preventDefault() を付けた部品は、スクロール・URL・履歴のどれも変わりませんでした。onclick 属性の中の return false でも移動は止まりますが、CSP では onclick 属性そのものがブロックされます。イベントの付け方は関連記事「addEventListenerの使い方|イベント一覧と解除・イベント委譲」で扱っています。
以前のコードを書き換える手順
javascript: を含む href を探す
grep -rn 'href="javascript:' src/ のように一覧にし、それぞれが「その場の操作」か「移動」かを分ける。
その場の操作は button に替える
a を button type="button" にし、見た目は CSS で合わせる。
onclick 属性を外部の .js に移す
addEventListener で付ける。数が多いときは親要素に1つだけ付けるイベント委譲が便利。
移動のリンクには本物の URL を入れる
画面内で開くなら click で preventDefault()。新しいタブで開く操作はそのまま通す。
キーボードと CSP で確かめる
Tab・Enter・Space で操作し、Report-Only の CSP を返してコンソールに違反が出ないことを見る。
javascript:void(0)と表示されて動かないとき(閲覧者向けの対処)
この節では、サイトを見ていてリンクが反応せず、画面の下に javascript:void(0) と出たときに、自分でできることが分かります。
javascript:void(0) はエラーの表示ではなく、そのリンクが JavaScript で動く作りだという印です。 動かないのは、JavaScript が止められている・読み込みに失敗した・拡張機能がブロックした、のどれかであることが多く、手元の実験でも JavaScript を無効にすると void(0) のリンクは何も起きませんでした。Java(プログラムの実行環境)のインストールとは関係ありません。
少し待ってから再読み込みする
ページの読み込みが終わる前に押すと、処理がまだ付いていないことがある。再読み込みしてから押し直す。
JavaScript が許可されているか確かめる
Chrome(パソコン)は、右上のその他のオプション →[設定]→[プライバシーとセキュリティ]→[サイトの設定]→[コンテンツ]の[JavaScript]で「サイトが JavaScript を使用できるようにする」を選ぶ(Google のヘルプの手順)。サイトごとの設定は、アドレスバーの左のサイト情報 →[サイトの設定]で変えられる。
拡張機能を止めて開き直す
広告ブロックやスクリプトを止める拡張機能が、処理のファイルを読み込ませていないことがある。一時的に止めて同じページを開く。
ポップアップのブロックを確かめる
新しいウィンドウを開くリンクは、ポップアップのブロックで止まることがある。アドレスバーにブロックの表示が出ていないかを見る。
別のブラウザで開き、サイトに知らせる
別のブラウザでも動かなければ、サイト側の不具合の可能性が高い。どのページのどのリンクかを添えて問い合わせる。
リンクの「新しいタブで開く」も効きません。手元の実験では、void(0) のリンクを Ctrl+クリック・中クリックしても新しいタブは開きませんでした。これは閲覧者の設定ではなく、リンクの作りによるものです。
javascript:void(0)とSEO・スクレイピングでの扱い
この節では、検索エンジンとプログラム(スクレイピング)から javascript:void(0) のリンクがどう見えるかが分かります。
Google 検索セントラルは、href に javascript: を書いたリンクを「非推奨(ただし、同様に解決を試みることはある)」の例に挙げています。 Google が確実にたどれるのは、href 属性に URL を持つ a 要素です。
<!-- 推奨(Google が解析可能) -->
<a href="/products/category/shoes">靴</a>
<!-- 非推奨の例として Google が挙げている形 -->
<a href="javascript:goTo('products')">商品</a>
<a onclick="goto('https://example.com')">…</a>
ブラウザの中でも、href の値はそのまま javascript:void(0) です。手元で読み取った値です。
| 部品 | getAttribute("href") | 要素の .href |
|---|---|---|
| void(0) のリンク | javascript:void(0) | javascript:void(0) |
| href="#" | # | http://127.0.0.1:47067/compare.html# |
| button | null | (プロパティが無い) |
| a(href なし) | null | 空の文字列 |
- スクレイピングで移動先を知りたいとき、href からは取れません。 移動先は onclick の中や data- 属性、JavaScript の処理の中にあります。自分が扱ってよいサイトなら、Playwright などのブラウザ自動操作でクリックし、移動後の URL を読む方法があります。
- 移動のリンクに本物の URL を入れておけば、検索エンジンもプログラムも同じ URL をたどれます。
javascript:void(0)のよくあるエラー・つまずき(原文つき)
この節では、javascript:void(0) まわりで出る文言と、原因・直し方の対応が分かります。
| 出た文言・症状 | 原因 | 直し方 |
|---|---|---|
| Running the JavaScript URL violates the following Content Security Policy directive 'script-src 'self''. … The action has been blocked. | CSP が javascript: URL を止めた | button+addEventListener に書き換える |
| Executing inline event handler violates the following Content Security Policy directive … | onclick 属性を CSP が止めた | 外部の .js で addEventListener |
| This document requires 'TrustedScript' assignment. Navigating to a javascript:-URL is equivalent to a 'TrustedScript' assignment. | Trusted Types のポリシー | javascript: URL をやめる |
| Error: React has blocked a javascript: URL as a security precaution. | React 19 が href を書き換えた | button と onClick にする |
| クリックするとページが文字だけになった | javascript: の結果が文字列だった | void 関数() にするか、href をやめる |
| クリックするとページの先頭に戻る | href="#" で移動した | button にするか preventDefault() |
| 戻るを押しても前のページに戻らない | href="#" が履歴を1つ増やした | 同上 |
| SyntaxError: Unexpected end of input | void の後ろに式が無い | void 0 のように式を書く |
| Space キーでボタンが押せない | a タグで作っている | button にする |
- 1コンソールの文言で CSP か React かを見分ける「Content Security Policy」なら CSP、「React has blocked」なら React
- 2応答ヘッダーの Content-Security-Policy を見るDevTools のネットワークのタブか
curl -I。nginx や CDN が後から付けていることがある - 3Report-Only で先に違反を洗い出す止めずにコンソールに info で記録される。手元でも同じ文言が出た
- 4エラー監視に同じ例外が溜まっていないか見るReact 19 では、画面が動いていてもクリックのたびに例外が出る
javascript:void(0)・href="#"・buttonのどれを使うか(判断表)
この節では、作りたい動きごとに、どの書き方を選ぶかが分かります。
- 1別のページ・別の場所へ移動する → 本物の URL を持つ aページ内の見出しへは href="#見出しのid"
- 2その場で何かが起きる → button type="button"メニュー・モーダル・タブ切り替え・いいね
- 3移動先もあるが画面内で開きたい → a+preventDefault()JavaScript が無くても移動先で読める
- 4フォームを送る → button type="submit"送信の処理は form の submit イベントで
- 5以前のコードで直ちに書き換えられない → void(0) のまま、CSP の影響を確かめるReact 19・CSP・Trusted Types のどれかを入れる前に書き換える
| 観点 | javascript:void(0) | href="#" | button |
|---|---|---|---|
| クリックで移動しない | しない | 先頭へ移動する | しない |
| URL・履歴が変わる | 変わらない | 変わる | 変わらない |
| Space キーで押せる | 押せない | 押せない | 押せる |
| 伝わるロール | link | link | button |
| CSP(script-src 'self') | ブロック | 動く(onclick 属性なら止まる) | 動く(addEventListener) |
| React 19 | エラーになる | preventDefault で動く | 動く |
| 向いている用途 | 以前のコードの維持だけ | ページ内リンクだけ | その場の操作すべて |
リンクそのものの書き方は関連記事「HTML aタグのリンクの書き方|target=_blank・ページ内リンク」で、利用者が入れた値を href に入れる危険は関連記事「XSS(クロスサイトスクリプティング)対策|フレームワーク別の注意点」で扱っています。
よくある質問
Q. javascript:void(0) とは何ですか? A. a タグの href に書いて、クリックしてもページを移動しないリンクにする書き方です。javascript: は「後ろのコードを実行する」URL、void(0) は「0 を評価して undefined を返す」式で、結果が undefined なのでブラウザは何もしません。
Q. void(0) の 0 には意味がありますか? A. ありません。void 1 でも void "abc" でも結果は undefined でした。短くて副作用が無いので 0 が慣例になっています。
Q. javascript:void(0) はエラーですか? A. エラーではありません。リンクにマウスを乗せたときに href の値が表示されているだけです。押しても反応しないときは、JavaScript の許可・拡張機能・再読み込みを確かめます。
Q. href="#" と javascript:void(0) はどちらがよいですか? A. その場の操作なら、どちらでもなく button がよい選択です。比べると、href="#" は先頭へ戻り URL と履歴が変わり、javascript:void(0) は CSP と React 19 で止まります。
Q. void(0) と undefined は同じですか? A. 値は同じ undefined です。以前はグローバルの undefined を書き換えられたため、確実な void 0 が使われました。今は書き換えできず、関数の中で同じ名前の変数を作ったときだけ違いが出ます。
Q. Chrome と Edge で挙動は違いますか? A. どちらも Chromium をもとにしているため、この記事で測った Chromium と同じ考え方で動きます。CSP や拡張機能の設定はブラウザごとに違うので、動かないときは設定を見比べます。
Q. javascript:void(0) のリンクを新しいタブで開けません。 A. 移動先の URL が無いためです。手元でも Ctrl+クリック・中クリックで新しいタブは開きませんでした。作る側が本物の URL を href に入れれば開けるようになります。
Q. React で href="javascript:void(0)" を書くとどうなりますか? A. React 19 では href が「エラーを投げる URL」に書き換えられ、クリックのたびに「React has blocked a javascript: URL as a security precaution.」の例外が出ます。onClick は動くので、気づかないまま例外が溜まります。
Q. return false と preventDefault() の違いは何ですか? A. onclick 属性の中の return false は、既定の動き(移動)を止めます。addEventListener の中では return false では止まらず、preventDefault() を呼びます。CSP では onclick 属性そのものが止まるので、preventDefault() の形をおすすめします。
Q. void 演算子は、今は使い道がありませんか?
A. あります。アロー関数で戻り値を使わないことを示す () => void doSomething() や、Promise を待たないことを明示する書き方、圧縮後のコードの void 0 で見かけます。
まとめ
- javascript:void(0) は、リンクを押しても移動しないようにする書き方。void はどんな式でも undefined を返し、0 に意味は無い。
- javascript: の結果が文字列だとページが置き換わる。void はそれを防ぐために付けてきた。
- href="#" は先頭へ戻り、URL と履歴が変わり、base タグがあると別ページへ移動した。void(0) と button は何も変わらなかった。
- CSP の script-src 'self' では「Running the JavaScript URL violates …」でブロックされ、React 19 は「React has blocked a javascript: URL …」の例外にする。
- 今の推奨は、その場の操作は button type="button"+addEventListener、移動は本物の URL を持つ a(画面内で開くなら preventDefault())。
参考・出典
確認日はいずれも 2026年10月29日です。
- MDN「void 演算子」:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/void
- MDN「javascript: URLs」:https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/javascript
- MDN「CSP: script-src」:https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src
- W3C「Content Security Policy Level 3」:https://w3c.github.io/webappsec-csp/
- React 公式ブログ「React v16.9.0 and the Roadmap Update」(Deprecating javascript: URLs):https://legacy.reactjs.org/blog/2019/08/08/react-v16.9.0.html
- Google 検索セントラル「Google 向けにリンクをクロール可能にする」:https://developers.google.com/search/docs/crawling-indexing/links-crawlable?hl=ja
- Google ヘルプ「ブラウザで JavaScript を許可する」:https://support.google.com/admanager/answer/12654?hl=ja
- Google Chrome ヘルプ「サイトの権限設定を変更する」:https://support.google.com/chrome/answer/114662?hl=ja
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「javascript:void(0)とは|意味・#との違いとCSPエラーの直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。