ブラウザには各イベントに対して「デフォルト動作」が定義されており、preventDefault() を呼び出すことでその動作を抑制できます。
本記事では、イベントの種類ごとに整理してまとめました。
Note
- ❌
preventDefault()で抑制できる - ⚠️
preventDefault()では抑制できない(別手段が必要) - ✅
preventDefault()で特定の動作をトリガーできる
1. マウスイベント(Mouse Events)
| イベント | デフォルト動作 |
preventDefault() の結果 |
備考 |
|---|---|---|---|
click on <a>
|
href のURLへ遷移 |
❌ ページ遷移しない | SPAルーティングなどに活用 |
click on <button type="submit">
|
フォームをサブミット | ❌ サブミットしない | |
click on <input type="checkbox">
|
チェック状態をトグル | ❌ 状態が変わらない | |
click on <input type="radio">
|
ラジオボタンを選択 | ❌ 選択されない | |
dblclick |
テキストを選択 | ❌ テキスト選択されない | |
contextmenu |
コンテキストメニューを表示 | ❌ メニューが表示されない | 右クリックメニューの無効化 |
mousedown + mouseup
|
テキストを範囲選択 | ❌ テキスト選択されない | |
dragstart on 画像/リンク |
ドラッグ開始(幽霊イメージ生成) | ❌ ドラッグできない | |
drag on element |
要素を移動 | ❌ 移動しない | |
drop |
ファイル/リンクを処理 | ❌ ドロップ処理されない | |
wheel |
ページをスクロール | ❌ スクロールしない |
passive: false が必要(後述) |
2. キーボードイベント(Keyboard Events)
| イベント | デフォルト動作 |
preventDefault() の結果 |
備考 |
|---|---|---|---|
keydown: Enter(input内) |
フォームをサブミット | ❌ サブミットしない | |
keydown: Tab |
次の要素へフォーカス移動 | ❌ フォーカスが移動しない | カスタムエディタでのインデントに活用 |
keydown: Space(ボタン上) |
ボタン/チェックボックスを有効化 | ❌ 有効化されない | |
keydown: Arrow keys |
ページスクロール/カーソル移動 | ❌ スクロールしない | |
keydown: Ctrl/Cmd + S |
ページを保存 | ❌ 保存しない | カスタム保存処理に活用 |
keydown: Ctrl/Cmd + P |
印刷ダイアログを開く | ❌ 印刷ダイアログが開かない | カスタム印刷処理に活用 |
keydown: Ctrl/Cmd + F |
検索ダイアログを開く | ❌ ダイアログが開かない | |
keydown: Ctrl/Cmd + C/X/V |
コピー/カット/ペースト | ❌ クリップボード操作を無効化 | |
keydown: F5 / Ctrl+R |
ページをリロード | ❌ リロードしない | ユーザー体験を損なうため注意 |
keydown: F12 |
DevToolsを開く | ⚠️ 抑制できない | ブラウザのセキュリティ仕様 |
keypress(文字/数字キー) |
inputへ文字を入力 | ❌ 文字が入力されない | ⚠️ Deprecated — keydown を使うこと |
3. フォームイベント(Form Events)
| イベント | デフォルト動作 |
preventDefault() の結果 |
備考 |
|---|---|---|---|
submit |
データをサーバーへ送信・ページリロード | ❌ 送信・リロードしない | AJAXによる非同期送信に活用 |
reset |
全inputを初期値にリセット | ❌ リセットしない | |
change on <select>
|
選択オプションを変更 | ❌ 選択が変わらない | |
input |
inputの値を更新 | ⚠️ 抑制できない |
readonly 属性を使うこと |
focus |
アウトラインを表示・カーソルを入れる | ⚠️ 抑制できない | CSS outline: none または blur() を使うこと |
4. メディアイベント(Media Events)
| イベント | デフォルト動作 |
preventDefault() の結果 |
備考 |
|---|---|---|---|
play on <video>/<audio>
|
再生開始 | ❌ 再生されない | |
pause |
一時停止 | ❌ 一時停止されない | |
volumechange |
音量を変更 | ❌ 音量が変わらない | |
seeked |
指定時刻へジャンプ | ❌ ジャンプしない |
5. タッチイベント(Touch Events)
| イベント | デフォルト動作 |
preventDefault() の結果 |
備考 |
|---|---|---|---|
touchstart |
スワイプ開始・ページスクロール | ❌ スクロール・ズームしない |
passive: false が必要 |
touchmove |
スクロール/ズーム | ❌ スクロールしない |
passive: false が必要 |
touchend |
スワイプ終了・クリック発火 | ❌ クリックが発火しない |
6. その他のイベント(Other Events)
| イベント | デフォルト動作 |
preventDefault() の結果 |
備考 |
|---|---|---|---|
copy |
選択テキストをクリップボードへコピー | ❌ コピーできない | コンテンツ保護 |
cut |
選択テキストをクリップボードへカット | ❌ カットできない | |
paste |
クリップボードからテキストを貼り付け | ❌ 貼り付けできない | 機密フィールドでの利用例あり |
beforeunload |
ページを離れる・タブを閉じる | ✅ 確認ダイアログを表示 | Chrome 51以降はカスタムメッセージ不可 |
dragenter / dragover
|
ドロップゾーンへのファイル受け入れ | ❌ ドロップできない |
drop を機能させるには必須 |
selectstart |
テキスト選択の開始 | ❌ テキスト選択できない | |
selectionchange |
選択範囲の変更 | ⚠️ 抑制できない |
注意事項
passive: false が必要なイベント
wheel・touchstart・touchmove はパフォーマンス最適化のため、ブラウザがデフォルトで passive: true に設定しています。
preventDefault() を有効にするには、addEventListener の第3引数に { passive: false } を明示する必要があります。
// NG: passive: true がデフォルトのため preventDefault() が無視される
document.addEventListener('touchmove', (e) => {
e.preventDefault();
});
// OK: passive: false を明示する
document.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
抑制できないブラウザ/OS の操作
セキュリティ上の理由から、以下の操作は preventDefault() では抑制できません。
-
F12— DevTools を開く -
Ctrl+Alt+Del— OSのシステム操作 -
Alt+F4— ウィンドウを閉じる
keypress は非推奨
keypress イベントはHTML仕様から非推奨(Deprecated) となっています。
今後は keydown または keyup を使用してください。
// 非推奨
element.addEventListener('keypress', handler);
// 推奨
element.addEventListener('keydown', handler);
beforeunload のカスタムメッセージ
Chrome 51以降、セキュリティ上の理由から beforeunload でカスタムメッセージを表示することはできません。
ブラウザが用意したデフォルトのメッセージのみ表示されます。
window.addEventListener('beforeunload', (e) => {
e.preventDefault();
e.returnValue = ''; // この文字列は表示されない(Chrome 51+)
});
クイックリファレンス(用途別まとめ)
| やりたいこと | 対象イベント |
|---|---|
| リンクのページ遷移を止める |
click on <a>
|
| フォームのリロードなしで送信 | submit |
| 右クリックメニューを無効化 | contextmenu |
| カスタムショートカットを実装 |
keydown(Ctrl+S など) |
| カスタムドラッグ&ドロップ |
dragstart, dragover, drop
|
| コンテンツのコピーを禁止 |
copy, selectstart
|
| モバイルのスクロールを制御 |
touchmove(+ passive: false) |
| ページ離脱の確認ダイアログ | beforeunload |
コードサンプル
// 1. リンクのページ遷移を止める
document.querySelectorAll('a[data-prevent]').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
console.log('ページ遷移をブロック');
});
});
// 2. フォームのAJAX送信
document.getElementById('myForm').addEventListener('submit', (e) => {
e.preventDefault();
console.log('フォームをAJAXで処理する');
});
// 3. 右クリックメニューを無効化
document.addEventListener('contextmenu', (e) => {
e.preventDefault();
});
// 4. コピーを禁止
document.addEventListener('copy', (e) => {
e.preventDefault();
alert('このコンテンツはコピーできません');
});
// 5. カスタムショートカット(Ctrl+S)
document.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
e.preventDefault();
saveCustom(); // 独自の保存処理
}
});
// 6. ホイールスクロールを制御(passive: false 必須)
document.addEventListener('wheel', (e) => {
e.preventDefault();
}, { passive: false });
// 7. モバイルのスクロールを制御(passive: false 必須)
document.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
// 8. ページ離脱の確認
window.addEventListener('beforeunload', (e) => {
e.preventDefault();
e.returnValue = '';
});
// 9. Tabキーをインデントとして使う(カスタムエディタ)
document.getElementById('editor').addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
e.preventDefault();
document.execCommand('insertText', false, ' ');
}
});
// 10. 機密フィールドへのペーストを禁止
document.getElementById('creditCard').addEventListener('paste', (e) => {
e.preventDefault();
alert('手動で入力してください');
});
Happy Codding!