This page shows how to use the JavaScript onMouseOver event (mouseover) to run code the moment the mouse pointer enters an element, and how to avoid common pitfalls such as repeated firing inside child elements.
マウスカーソルが要素の上に「乗った瞬間」に、ちょっとした反応(色を変える、メッセージを出す、プレビューを切り替えるなど)を JavaScript で付けたいときに使う onmouseover(mouseover)の使いどころと基本パターンをまとめたページ。
onmouseover(正式には mouseover イベント/onmouseover プロパティ)は、マウスカーソルが要素の上に入った瞬間に実行されるイベントハンドラです。
「ボタンに乗せたらハイライトする」「カードに触れたら詳細を出す」「サムネに触れたらプレビューを切り替える」など、いわゆる “ホバー(hover)” の動きを JavaScript 側で制御したいときに出番があります。
ただし、見た目の変化だけで済む場合は、まず CSS の :hover を検討するのが基本です。JavaScript が必要なのは「状態を持つ」「条件分岐する」「ログや通信をしたい」など、見た目だけでは完結しないときです。
以下は、onmouseover の基本的な使い方です。
HTML
<div id="hoverBox">ここにマウスを乗せてください</div>
JavaScript
// 要素の onmouseover プロパティにハンドラーを追加する
document.getElementById("hoverBox").onmouseover = function () {
console.log("mouseover: 乗りました");
};
Sample
この例では、div 要素に対して onmouseover を設定し、カーソルが入ったタイミングでメッセージを表示しています。
なお、onmouseover は “プロパティ” なので、同じ要素に別の onmouseover を代入すると上書きされます。複数の処理を安全に追加したい場合は、次の addEventListener を使うのが一般的です。
onmouseover でも動きますが、実務ではだいたい次の理由で addEventListener の方が扱いやすいです。
once や capture などのオプションが使えるJavaScript
const box = document.getElementById("hoverBox");
box.addEventListener("mouseover", function () {
console.log("addEventListener: mouseover");
});
HTML に onmouseover="..." と直接書く方法もありますが、HTML と JavaScript が混ざりやすく保守しづらいので、基本は「JS側でまとめて登録」でOKです。
mouseover(= onmouseover)は、要素の中に子要素があると「親に入った」「子に入った」「子から別の子に移動した」などでも発火しやすい、という特徴があります。
つまり、親要素に対して mouseover を付けると、子要素の上にマウスが移動しただけで “何回も” 起きることがあります。バグっぽく見えますが、仕様としてよくある動きです。
HTML
<div id="card" style="padding: 16px; border: 1px solid #ccc;">
親要素
<button style="margin-left: 8px;">子ボタン</button>
</div>
<p id="cardLog"></p>
JavaScript
const card = document.getElementById("card");
const cardLog = document.getElementById("cardLog");
let count = 0;
card.addEventListener("mouseover", function () {
count += 1;
cardLog.textContent = "mouseover 発火: " + count + " 回";
});
Sample
「カード全体に入ったときに 1 回だけ処理したい」のに回数が増える場合、次の mouseenter の方が素直に作れます。
mouseenter は、その要素に入った瞬間を扱いやすいイベントです。mouseover と違って、子要素への移動で増えにくく、バブリングもしません。
JavaScript
const card = document.getElementById("card");
card.addEventListener("mouseenter", function () {
card.style.background = "#f5f5f5";
});
card.addEventListener("mouseleave", function () {
card.style.background = "";
});
「入ったとき」「出たとき」をセットで作るなら、mouseenter + mouseleave は相性が良いです。
ただし、後で紹介するイベント委譲(親にまとめて付ける)をしたい場合は、バブリングする mouseover の方が都合がいい場面もあります。
mouseover / mouseout には「どこから来た/どこへ行った」が入っています。これが event.relatedTarget です。
親要素の中で子要素に移動しただけなら無視して、外から入ったときだけ反応させたい場合は、relatedTarget と contains() を組み合わせると、暴発を抑えられます。
JavaScript
const card = document.getElementById("card");
card.addEventListener("mouseover", function (event) {
const from = event.relatedTarget;
// カードの中からカードの中へ移動しただけなら無視する
if (from && card.contains(from)) {
return;
}
card.style.outline = "2px solid #666";
});
card.addEventListener("mouseout", function (event) {
const to = event.relatedTarget;
// カードの中からカードの中へ移動しただけなら無視する
if (to && card.contains(to)) {
return;
}
card.style.outline = "";
});
この考え方を知っていると、「mouseover が増えるのをバグ扱いせず、仕様として制御する」方向に進めます。
サムネ画像が増える・リスト項目が動的に増える、などのケースでは、各要素にリスナーを付けるより、親要素に 1 個だけ付けてまとめるほうが管理がラクです。これがイベント委譲です。
このとき、バブリングする mouseover は相性が良いです。
HTML
<img id="mainPreview" src="main.jpg" alt="メイン画像" style="width: 320px; display: block; margin-bottom: 8px;">
<div id="thumbs">
<img src="a.jpg" alt="サムネA" style="width: 80px; cursor: pointer;">
<img src="b.jpg" alt="サムネB" style="width: 80px; cursor: pointer;">
<img src="c.jpg" alt="サムネC" style="width: 80px; cursor: pointer;">
</div>
JavaScript
const main = document.getElementById("mainPreview");
const thumbs = document.getElementById("thumbs");
thumbs.addEventListener("mouseover", function (event) {
const img = event.target.closest("img");
if (!img) {
return;
}
main.src = img.src;
});
event.target は “いちばん内側” になりがちなので、closest() で目的の要素を探すと安定します。親側でまとめて扱えるので、要素が増減しても壊れにくいです。
mouseover は発火回数が増えやすいので、DOMを大量にいじる処理や通信をそのまま入れると重くなりやすいです。:hover が軽くて安全です。focus/blur も併用すると丁寧です。たとえばツールチップのような UI は、hover だけにするとスマホやキーボード操作で詰みやすいので、focus でも出るようにしておくと安心です。
:hover が基本おすすめです。状態管理・ログ・分岐など、JavaScript の処理が必要なら onmouseover(または addEventListener("mouseover", ...))を使います。mouseenter を検討するか、relatedTarget を使って「外から入った時だけ」に絞ります。mouseover はバブリングして子要素移動でも発火しやすい一方、mouseenter は基本的にその要素に入った瞬間だけで、バブリングしません。addEventListener で分けて書くほうが保守しやすいことが多いです。getElementById の ID)が間違っている、またはスクリプトが先に実行されて要素がまだ存在しない可能性があります。HTMLの後ろで読み込むか、defer や DOMContentLoaded を使います。mouseover の仕様で、子要素への移動でも発火します。mouseenter に切り替えるか、relatedTarget を使って「外から入った時だけ」に絞ります。event.target は内側の要素になりがちです。親にまとめたい場合は event.currentTarget を見るか、closest() で目的の要素を探します。mouseover で重い DOM 操作や通信をすると体感が悪くなります。見た目だけなら CSS に寄せる、処理を間引く(デバウンス)などが有効です。