【2026年最新】バブリングとは?JSイベント伝播の仕組みと停止法

目次
【2026年最新】バブリングとは?JSイベント伝播の仕組みと停止法
【2026年最新】バブリングとは?JSイベント伝播の仕組みと停止法
@ creator • Click to Play Video Inline
🎵 【2026年最新】バブリングとは?JSイベント伝播の仕組みと停止法

Webフロントエンド開発において、「子要素のボタンをクリックしただけなのに、なぜか親要素の枠線や背景のクリックイベントまで勝手に発火してしまった」というトラブルに直面した経験はないでしょうか。この挙動の正体こそが、JavaScriptのDOMイベント処理における基本概念である「バブリング(Event Bubbling)」です。

バブリングは一見すると予期せぬバグの温床に見えますが、ブラウザがDOMツリーを通じてイベントを処理する合理的な仕組みであり、適切に活用すればコードの軽量化や保守性の向上に直結します。本稿では、イベント伝播の全貌からキャプチャリングとの違い、実務で必須となるstopPropagationを用いた制御法までを徹底解説します。

📌 【この記事の重要ポイントまとめ】
  • 要点1:バブリングとは、子要素で発生したDOMイベントが水中の泡のように親要素へと順次伝播していくブラウザの標準仕様である。
  • 要点2:イベント伝播は「キャプチャリング」「ターゲット」「バブリング」の3段階で構成され、通常のイベントリスナーはバブリング時に発火する。
  • 要点3:event.stopPropagation()でバブリングを安全に停止できる一方、ブラウザの既定動作を止めるpreventDefault()との役割の違いを正確に把握しておく必要がある。

【仕組みを解剖】JavaScriptの「バブリング」とは何か?泡のように浮き上がるイベント伝播

バブリングとは、HTMLドキュメント内で特定の要素(ボタンやリンクなど)にクリックやキー入力などのDOMイベントが発生した際、そのイベントが発生元の要素から親要素、さらにその祖先要素へと順番に伝わっていく現象を指します。水底から水面に向かって気泡(Bubble)がポコポコと浮き上がっていく様子に似ていることから、その名が付けられました。

例えば、<div class="card">の中に<button>が配置されているマークアップを想像してください。ユーザーがボタンをクリックした瞬間、ブラウザ内部ではボタン自体のクリックイベントハンドラが動作するだけでなく、直上の&div>、さらには<body>、<html>、最上位のwindowオブジェクトにまでクリックの通知が駆け上がっていきます。

JavaScriptのイベントリスナー(addEventListener)は、デフォルト状態でこのバブリングフェーズを検知して関数を実行するように設計されています。この仕様を意識せずに親要素と子要素の双方に処理を記述していると、意図しない多重実行やレイアウト崩れといった不具合の原因になります。

【3つのフェーズ】キャプチャリング・ターゲット・バブリングの決定的な違い

ブラウザがDOMツリー上でイベントを伝達する一連の流れを「イベント伝播(Event Propagation)」と呼びます。このプロセスは単に下から上へ昇るだけでなく、厳密には次の3つのフェーズを経由して処理されています。

第1段階が「キャプチャリングフェーズ(Capturing Phase)」です。ユーザーのアクションが発生すると、イベントはまず最上位のwindowから始まり、DOMツリーの階層を一段ずつ下りながらターゲット要素を目指して下降します。普段はあまり意識されませんが、すべてのイベントはこの親から子への探索からスタートします。

第2段階が「ターゲットフェーズ(Target Phase)」です。イベントが実際にクリックされた対象要素へ到達した瞬間を指し、その要素に直接登録されたハンドラが呼び出されます。

そして第3段階が「バブリングフェーズ(Bubbling Phase)」です。ターゲットに到達したイベントが反転し、今度は子要素から親要素、祖先要素へと上流に向かって駆け上がっていきます。一般的なWeb制作やアプリ開発で目にする「親要素への伝播」は、すべてこの第3フェーズで起きている事象です。

【なぜ起きる?】クリックが親要素へ伝播する原因と現場で起きるトラブル事例

なぜJavaScriptにはこのような親要素・子要素への伝播の仕組みが存在するのでしょうか。その最大の理由は、UIコンポーネントの柔軟な設計とイベント処理の効率化にあります。もしバブリングがなければ、階層構造を持つ複雑なUIにおいて、親要素側で子の状態変化をキャッチすることが極めて困難になります。

しかし、設計を誤ると現場では頻繁にトラブルの火種となります。代表的なのが、モーダルウィンドウの実装です。モーダルの背景(黒い半透明エリア)をクリックしたときにモーダルを閉じる処理を仕掛けた際、中央のモーダルコンテンツ内をクリックしただけで背景の閉じる処理まで連動して発火し、意図せず画面が閉じてしまうバグは非常によく見られます。

また、カード型UIの中に「お気に入り追加ボタン」や「共有リンク」を内包しているケースでも、ボタンを押した瞬間にカード全体の遷移処理が走ってしまうといった事故が後を絶ちません。これらはすべて、子要素のイベントが親要素へと伝播するバブリング現象が原因です。

【コード付き解説】stopPropagationによるバブリング停止とpreventDefaultとの違い

意図しない親要素への伝播を防ぐには、イベントオブジェクトが持つstopPropagation()メソッドを使用してバブリングの停止を実行します。

使い方は極めてシンプルです。イベントリスナーに渡されるイベントオブジェクト(eまたはevent)に対し、処理の途中でメソッドを呼び出します。

const childButton = document.querySelector('.child-btn');
childButton.addEventListener('click', (event) => {
  event.stopPropagation();
  console.log('子要素のボタンだけが実行されました');
});

ここで多くの開発者が混同しやすいのが、stopPropagationとpreventDefaultの違いです。stopPropagation()は「DOMツリーを伝わるイベントの伝播(バブリング/キャプチャリング)を途中で遮断する命令」です。一方のpreventDefault()は、「<a>タグのページ遷移や<form>タグの送信リロードなど、ブラウザ標準のデフォルト挙動を無効化する命令」であり、親要素へのイベント伝播自体を止める力はありません。

両者の役割は全く異なるため、目的に応じて正しく使い分ける、あるいは必要に応じて双方を併用する判断が求められます。

【実践テクニック】イベント委譲(デリゲーション)で実現する軽量・高速なDOM設計

バブリングはトラブルの原因になるだけではありません。その性質を逆手に取った強力な実装手法が「イベント委譲(Event Delegation)」です。

例えば、100行以上あるリスト項目(<li>)の一つひとつに個別のイベントリスナーを登録すると、ブラウザのメモリ消費量が増大し、描画パフォーマンスの低下を招きます。また、非同期通信で後から動的に追加された要素にはイベントが効かないという問題も発生します。

そこで、親要素である<ul>に1つだけリスナーを登録しておき、子要素から上がってきたバブリングイベントを親側で一括検知します。イベントオブジェクトのevent.targetを参照すれば「実際にどの子要素がクリックされたか」を特定できるため、わずか1つのハンドラで大量の要素や動的要素をスマートに制御可能です。

【豆知識】Web開発だけじゃない?看護・医療現場で使われる「バブリング音」とは

「バブリング」という単語はIT・Web業界の専門用語として知られていますが、実は看護・医療現場でも日常的に使われる専門用語です。

医療分野におけるバブリングとは、気管挿管や人工呼吸器の管理中、あるいは気道内に喀痰(かくたん)や分泌物が貯留している際に聴取される「ブツブツ」「ゴロゴロ」とした呼吸副雑音(水泡音・バブリング音)を指します。分泌物の中を空気が通過する際に泡が弾けるような音が発生することからこう呼ばれ、看護師や医師が吸引の必要性を判断する重要な臨床指標となっています。

Web用語のバブリングも医療用語のバブリングも、「液体の中で気泡が湧き上がる物理現象」が語源である点は共通しています。検索時に医療系テキストがヒットしても混乱しないよう、文脈の違いを頭の片隅に留めておくと役立ちます。

【バブリングとは】に関するよくある質問(FAQ)

Q1:すべてのDOMイベントでバブリングが発生しますか?
A1:いいえ、すべてのイベントがバブリングするわけではありません。例えば、focusやblur、mouseenter、mouseleaveなどはバブリングしません(これらには代替としてバブリングするfocusinやfocusoutなどが用意されています)。イベントがバブリングするかどうかは、event.bubblesプロパティがtrueであるかを確認することで判定できます。

Q2:stopPropagation()とstopImmediatePropagation()の違いは何ですか?
A2:stopPropagation()は親要素や祖先要素への伝播を止めますが、同一要素に登録された他のリスナーの実行までは止めません。一方、stopImmediatePropagation()は親への伝播を遮断すると同時に、その要素に後から設定されている他のすべてのリスナーの実行も即座に停止させます。

Q3:キャプチャリングフェーズでイベントを拾いたい場合はどう書きますか?
A3:addEventListenerの第3引数に{ capture: true }または真偽値trueを渡します。これにより、バブリングフェーズではなく下降中のキャプチャリングフェーズでハンドラを実行させることが可能です。

まとめ:イベントフローを正しく制御しフロントエンドの不具合をゼロにする

JavaScriptのバブリングは、DOMツリーの構造上ごく自然に発生するイベント伝播の仕組みです。意図しない親要素の誤動作に遭遇した際は、まず「キャプチャリング・ターゲット・バブリング」のどの段階で何が起きているかを整理し、stopPropagation()をピンポイントで適用することが解決への近道となります。

さらに、イベント委譲を使いこなせば、コードの記述量を劇的に減らしながら高パフォーマンスなWebアプリケーションを構築できます。仕組みの表面だけをなぞるのではなく、ブラウザ内部の伝播ルールを深く理解して、堅牢でメンテナンス性の高いフロントエンド開発を目指しましょう。 (出典: バブリング と は(Yahoo!ニュース))