mouseleaveとmouseoutの違い

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

mouseleaveとmouseoutの基本動作

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

以下は、mouseleaveの例です。

【mouseleave利用例】
<div id="test-leave">
ここの範囲外にマウスを移動させます。
</div>

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

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

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

ここの範囲外にマウスを移動させます。

要素内にマウスカーソルを移動した後、要素外に移動すると、アラートが表示されます。

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

子要素から移動時の違い

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

以下は、mouseleaveの例です。

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

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

const x = document.querySelector("#test-leave");
x.addEventListener("mouseleave", func1);
</script>

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

赤字部分でマウスカーソルが枠内(div内)から外に移動すると、赤色に変わるようにしています。

実行例は、以下のとおりです。なお、5秒程度で戻るように追加で処理を入れています。

要素外にマウスを移動させると赤になります。 スペードA トランプ画像にマウスを移動させても赤になりません。

枠外に移動させると赤になります。5秒すると元に戻ります。枠内に移動した後、子要素であるトランプ上にマウスに移動させても色が変わりません。このため、内側から外側への移動だけイベントになっていることがわかると思います。

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

要素外にマウスを移動させると赤になります。 スペードA トランプ画像にマウスを移動させても赤になります。

枠内に移動した後、子要素であるトランプ上にマウスに移動させると赤になります。このため、子要素への移動でもイベントになっていることがわかると思います。

バブリングの違い

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

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

【mouseoutのバブリング例】
<div id="test-out">
トランプ画像にマウスを移動させると赤になって、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-out");
x.addEventListener("mouseout", func1);
</script>

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

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

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

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

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

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

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

トランプ上にマウスを移動させても文字は赤になりません。これは、すでに説明したとおり、子要素への移動ではmouseleaveがイベントにならないためです。

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

まとめ

mouseleaveは、要素外に移動した時に処理を実行し、子要素側への移動や子要素からのバブリングで実行しない時に使います。つまり、ターゲットとなる要素で1回だけ実行したい時に使います。

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

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

mouseoutのバブリング

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