mouseenterとmouseoverの違い

イベントリスナーのmouseenterとmouseoverの違いについて、サンプルコードを示しながら説明しています。

mouseenterとmouseoverの基本動作

mouseenterとmouseoverは、要素内にマウスカーソルが移動した時に処理を実行できます。

以下は、mouseenterの例です。

【mouseenter利用例】
<div id="test-enter">
ここにマウスを移動します。
</div>

<script>
const x = document.querySelector("#test-enter");
x.addEventListener("mouseenter", function(){alert("テストです");});
</script>

赤字部分でmouseenterイベントを登録しています。

実行例は、以下のとおりです。

ここにマウスを移動します。

要素内にマウスを移動すると、アラートが表示されます。

mouseenterの代わりに、mouseoverを使っても同じ動作になります。

子要素から移動時の違い

mouseenterは子要素から親要素にマウスカーソルが移動した時はイベントになりませんが、mouseoverはイベントになります。

以下は、mouseenterの例です。

【子要素がある時のmouseenter利用例】
<div id="test-enter1">
枠内にマウスを移動させると赤になります。<br>
トランプ画像にマウスを移動させると黒になります。
<img src="11.png" alt="スペードA" id="test-enter2">
再度トランプ画像の外にマウスを移動させるても赤になりません。
</div>

<script>
function func1() {
  x.style.color = "red";
}
function func2() {
  x.style.color = "black";
}

const x = document.querySelector("#test-enter1");
const y = document.querySelector("#test-enter2");
x.addEventListener("mouseenter", func1);
y.addEventListener("mouseenter", func2);
</script>

divの子要素として、img要素があります。

赤字部分でマウスカーソルが枠内(div内)に移動すると、赤色に変わるようにしています。青字部分は、マウスカーソルが画像内(img内)に移動した時の処理で、黒字になるようにしています。

実行例は、以下のとおりです。

枠内にマウスを移動させると赤になります。
トランプ画像にマウスを移動させると黒になります。 スペードA 再度トランプ画像の外にマウスを移動させるても赤になりません。

枠内に移動させると赤になり、子要素である画像に移動させると黒になります。子要素である画像から枠内に移動させても赤にはなりません。このため、外側から内側への移動だけイベントになっていることがわかると思います。

x.addEventListener("mouseenter", func1);のmouseenterを、mouseoverに変えた時の実行例は、以下のとおりです。

枠内にマウスを移動させると赤になります。
トランプ画像にマウスを移動させると黒になります。 スペードA 再度トランプ画像の外にマウスを移動させると赤になります。

枠内に移動させると赤になり、子要素である画像に移動させると黒になります。子要素である画像から枠内に移動させても赤になります。このため、内側から外側への移動でもイベントになっていることがわかると思います。

バブリングの違い

mouseenterはバブリング(子要素から親要素へ伝播)しませんが、mouseoverはバブリングします。

以下は、mouseoverを使った例です。

【mouseoverのバブリング例】
<div id="test-over">
枠内にマウスを移動させると赤になりますが、2秒で黒に戻ります。<br>
トランプ画像にマウスを移動させても赤になって、2秒で黒に戻ります。<br>
<img src="11.png" alt="スペードA">
再度トランプ画像の外にマウスを移動させても赤になり、2秒で黒に戻ります。
</div>

<script>
function func1() {
  x.style.color = "red";
  setTimeout(function(){x.style.color="black";},2000);
}
const x = document.querySelector("#test-over");
x.addEventListener("mouseover", func1);
</script>

mouseoverから呼び出されるfunc1では、文字を赤字に変更して2秒後に黒へ戻しています。mouseoverは、div要素がターゲットです。

実行例は、以下のとおりです。

枠内にマウスを移動させると赤になりますが、2秒で黒に戻ります。
トランプ画像にマウスを移動させても赤になって、2秒で黒に戻ります。
スペードA 再度トランプ画像の外にマウスを移動させても赤になり、2秒で黒に戻ります。

枠内にマウスを移動させると文字が赤になりますが、2秒で黒に戻ります。これは、divをターゲットにしたmouseoverにより、func1が呼び出されるためです。

トランプ画像上にマウスを移動させても文字が赤になり、2秒後に黒に戻ります。これは、imgをターゲットにmouseoverをイベントにしていませんが、バブリングによりdivのmouseoverが動作するためです。

トランプ画像上から外にマウスを移動させても同様ですが、これはすでに説明したように子要素からの移動でもmouseoverが動作するためです。

mouseoverの代わりに、mouseenterを使った場合の実行例は、以下のとおりです。

枠内にマウスを移動させると赤になりますが、2秒で黒に戻ります。
トランプ画像にマウスを移動させても赤になりません。
スペードA 再度トランプ画像の外にマウスを移動させても赤になりません。

枠内にマウスを移動させると文字が赤になり、2秒後に黒に戻るのはmouseoverと同じです。

トランプ画像上にマウスを移動させても文字の色は変わりません。これは、子要素から親要素への伝播であるバブリングが発生しないためです。また、子要素であるトランプ画像からの移動でも赤にはなりません。

まとめ

mouseenterは、要素内に移動した時に処理を実行し、その後は実行しない時に使います。つまり、ターゲットとなる要素で1回だけ実行したい時に使います。

mouseoverは、要素内に移動した時だけでなく、子要素に移動した時、子要素内で移動する時、子要素から戻る時など、複数回イベントを実行する時に使います。

なお、バブリングは子要素でイベントが発生した時に親要素へ伝播します。つまり、より親側(外側)にmouseoverが記述されている必要があります。

バブリングの動作

このため、子要素でmouseoverを記述していて、親要素にマウスを移動させても処理は実行されません。