結論

javascript:void(0) は「リンクを押しても、どこにも移動しない」ようにする書き方です。void 演算子はどんな式を渡しても undefined を返すため、ブラウザは何も表示を変えずにその場にとどまります。今は、ページを移動しないボタンには <button type="button"> を使うのが基本です。

この記事でわかること

  • void(0) の意味と、void 演算子の実行結果
  • href="javascript:void(0)"・href="#"・button の違い(Chromium で実測)
  • CSP と React 19 でブロックされたときのエラー原文と直し方

2026年10月29日更新|Chromium 153・Node.js 22・React 19.2で実行確認

リンクをクリックすると、まず 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>
1

javascript:

URL の種類(スキーム)。ブラウザは移動する代わりに、後ろに書いたコードを実行する。

http: や mailto: の仲間

2

void

JavaScript の演算子。後ろの式を評価して、結果を捨て、undefined を返す。

関数ではない

3

(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 に戻りました。閲覧者から見ると「戻るを押しても前のページに戻らない」状態になります。

2000→0pxhref="#" のスクロールクリックで先頭に戻った
+1href="#" の履歴void(0) と button は増えない
0枚void(0) を Ctrl+クリック新しいタブが開かない

新しいタブ・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(&#x27;React has blocked a javascript: URL as a security precaution.&#x27;)">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 があると別ページへ移動する
→
代わりにhref に本物の URL を入れ、click で 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の使い方|イベント一覧と解除・イベント委譲」で扱っています。

以前のコードを書き換える手順

1

javascript: を含む href を探す

grep -rn 'href="javascript:' src/ のように一覧にし、それぞれが「その場の操作」か「移動」かを分ける。

一覧化

2

その場の操作は button に替える

a を button type="button" にし、見た目は CSS で合わせる。

ロールが button になる

3

onclick 属性を外部の .js に移す

addEventListener で付ける。数が多いときは親要素に1つだけ付けるイベント委譲が便利。

CSP で止まらない

4

移動のリンクには本物の URL を入れる

画面内で開くなら click で preventDefault()。新しいタブで開く操作はそのまま通す。

検索にも拾われる

5

キーボードと CSP で確かめる

Tab・Enter・Space で操作し、Report-Only の CSP を返してコンソールに違反が出ないことを見る。

仕上げの確認

javascript:void(0)と表示されて動かないとき(閲覧者向けの対処)

この節では、サイトを見ていてリンクが反応せず、画面の下に javascript:void(0) と出たときに、自分でできることが分かります。

javascript:void(0) はエラーの表示ではなく、そのリンクが JavaScript で動く作りだという印です。 動かないのは、JavaScript が止められている・読み込みに失敗した・拡張機能がブロックした、のどれかであることが多く、手元の実験でも JavaScript を無効にすると void(0) のリンクは何も起きませんでした。Java(プログラムの実行環境)のインストールとは関係ありません。

1

少し待ってから再読み込みする

ページの読み込みが終わる前に押すと、処理がまだ付いていないことがある。再読み込みしてから押し直す。

まず試す

2

JavaScript が許可されているか確かめる

Chrome(パソコン)は、右上のその他のオプション →[設定]→[プライバシーとセキュリティ]→[サイトの設定]→[コンテンツ]の[JavaScript]で「サイトが JavaScript を使用できるようにする」を選ぶ(Google のヘルプの手順)。サイトごとの設定は、アドレスバーの左のサイト情報 →[サイトの設定]で変えられる。

Chrome

3

拡張機能を止めて開き直す

広告ブロックやスクリプトを止める拡張機能が、処理のファイルを読み込ませていないことがある。一時的に止めて同じページを開く。

広告ブロック等

4

ポップアップのブロックを確かめる

新しいウィンドウを開くリンクは、ポップアップのブロックで止まることがある。アドレスバーにブロックの表示が出ていないかを見る。

別ウィンドウを開くリンク

5

別のブラウザで開き、サイトに知らせる

別のブラウザでも動かなければ、サイト側の不具合の可能性が高い。どのページのどのリンクかを添えて問い合わせる。

閲覧者には直せない

リンクの「新しいタブで開く」も効きません。手元の実験では、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. 1別のページ・別の場所へ移動する → 本物の URL を持つ aページ内の見出しへは href="#見出しのid"
  2. 2その場で何かが起きる → button type="button"メニュー・モーダル・タブ切り替え・いいね
  3. 3移動先もあるが画面内で開きたい → a+preventDefault()JavaScript が無くても移動先で読める
  4. 4フォームを送る → button type="submit"送信の処理は form の submit イベントで
  5. 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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ
参加受付中

AI駆動開発、 無料セミナー