「クリックしたはずなのに、なぜか隣のボタンまで反応する…?」イベント伝播という不思議な現象を紐解こう
Web制作を始めたばかりの頃、こんな経験はありませんか?
「リストの中の小さなアイコンをクリックしただけなのに、なぜか親のリンク全体が反応して別のページに飛んでしまう……」
これ、実はバグでも何でもなくて、Webの世界では「イベント伝播(でんぱ)」という、とっても律儀なルールが働いているからなんです。今日は、インライン要素(``や``など)を使いこなす上で避けては通れない、この「イベントのバブリングと制御」について、一緒に紐解いていきましょう。
—
「イベント伝播」を、お買い物に例えてみよう
Webブラウザの世界では、私たちが画面をクリックすると、そのイベント(出来事)は「誰がクリックされたか?」から始まって、どんどん外側の親要素へと伝わっていきます。
これを「お買い物」で例えてみましょう。
1. 子要素(商品): あなたが棚にある「商品」を手に取ります。
2. 親要素(棚): 商品を手に取ると、同じ棚が揺れますよね。
3. さらに親(お店全体): 棚が揺れると、お店全体が「何かが起きたぞ!」と気づきます。
HTMLの世界でも同じです。あなたが``タグをクリックすると、その親である`
なぜ「伝播」を止めたくなるのか?
基本的にはこの「伝播」は便利な仕組みです。でも、困ることもありますよね。
例えば、「カード全体をクリックすると詳細ページへ飛ぶリンク」の中に、「お気に入りボタン」を配置したい場合です。
お気に入りボタンを押しただけなのに、カード全体が反応して詳細ページへ飛んでしまったら、ユーザーはイライラしてしまいますよね。ここで登場するのが、伝播をストップさせる魔法の呪文、`stopPropagation()`です。
実践!イベント伝播を制御するコード
では、実際にどうやって「ここから先には伝えないで!」とお願いするのか、コードを見てみましょう。
// HTMLのイメージ
//
カード全体(ここをクリックすると詳細ページへ行く)
//
//
const card = document.getElementById(‘card’);
const btn = document.getElementById(‘favorite-btn’);
// カード全体のクリックイベント
card.addEventListener(‘click’, () => {
console.log(‘カード全体がクリックされました!’);
});
// お気に入りボタンのクリックイベント
btn.addEventListener(‘click’, (event) => {
// ここが重要!「バブリング」をここで止めます
event.stopPropagation();
console.log(‘お気に入りボタンが押されました。カードには伝わりません!’);
});
この `event.stopPropagation()` を書くことで、お気に入りボタンをクリックした瞬間に、回覧板の配送がストップします。「カードさん、ごめんね。あとはこっちでやるから、気にしないで!」と伝えているイメージですね。
—
実務で「気をつけたい」3つのポイント
この知識、とっても便利なんですが、使うときにはいくつか注意点があります。
- 使いすぎには注意!: 全てのイベントで `stopPropagation()` を使うと、後から解析したいログツールや、UIの監視ツールが「何も起きない!」と混乱してしまいます。本当に必要な時だけ使うのがプロの流儀です。
- 「キャプチャリング」という逆流: 実はイベントには「外側から内側へ」向かうキャプチャリングという流れもあります。でも、初学者のうちはまずは「バブリング(内側から外側へ)」をしっかり理解すれば大丈夫ですよ!
- イベント委譲(Event Delegation)というテクニック: 逆に、伝播を逆手にとって「親要素で子要素のイベントをまとめて管理する」というテクニックもあります。これは少し慣れてきたら挑戦してみましょう。
最後に:つまずくのは、理解しようとしている証拠
「イベントが変な挙動をする……」と悩んでいるあなたは、それだけ細かいところまで画面の動きを観察できている素晴らしい証拠です。
Web制作は、一つひとつの仕組みが分かってくると、パズルのピースが埋まるように面白くなっていきます。もし今回うまくいかなくても、何度も試して、コンソール画面に `console.log` を出しながら遊んでみてくださいね。
皆さんのWeb制作ライフが、より楽しく、より自由なものになりますように!また次のステップでお会いしましょう。

コメント