JavaScript Mouse Events
Mouse events fire when the user interacts with elements using a pointing device. JavaScript provides a rich set of mouse events that cover clicks, movement, hovering, and right-click context menus.
Click Events
The click event fires when the user presses and releases the primary mouse button on an element. dblclick fires on a double-click. Both receive a MouseEvent object.
const box = document.getElementById("box");
box.addEventListener("click", (e) => {
console.log("Single click at", e.clientX, e.clientY);
});
box.addEventListener("dblclick", (e) => {
console.log("Double click at", e.clientX, e.clientY);
});mousedown and mouseup
mousedown fires when a mouse button is pressed, and mouseup fires when it is released. Together they form a click. The button property tells you which button was used (0 = left, 1 = middle, 2 = right).
const box = document.getElementById("box");
box.addEventListener("mousedown", (e) => {
console.log("Mouse down — button:", e.button);
// 0 = left, 1 = middle, 2 = right
});
box.addEventListener("mouseup", (e) => {
console.log("Mouse up — button:", e.button);
});mousemove
Fires continuously as the mouse pointer moves over an element. Because it fires very frequently, heavy operations inside the handler should be throttled for performance.
const canvas = document.getElementById("canvas");
canvas.addEventListener("mousemove", (e) => {
console.log(`Mouse at (${e.offsetX}, ${e.offsetY})`);
});
// Throttled version for better performance
let lastTime = 0;
canvas.addEventListener("mousemove", (e) => {
const now = Date.now();
if (now - lastTime > 100) { // fire at most every 100ms
console.log(`Throttled: (${e.offsetX}, ${e.offsetY})`);
lastTime = now;
}
});mouseenter / mouseleave vs mouseover / mouseout
These events detect when the pointer enters or leaves an element. The key difference is that mouseenter/mouseleave do NOT bubble and do NOT fire when moving between child elements, while mouseover/mouseout DO bubble and fire for child transitions.
const parent = document.getElementById("parent");
// Does NOT fire when moving between children
parent.addEventListener("mouseenter", () => {
console.log("mouseenter — entered parent");
});
parent.addEventListener("mouseleave", () => {
console.log("mouseleave — left parent");
});
// DOES fire when moving between children (bubbles)
parent.addEventListener("mouseover", () => {
console.log("mouseover — fires for children too");
});
parent.addEventListener("mouseout", () => {
console.log("mouseout — fires for children too");
});| Event pair | Bubbles? | Fires for child transitions? |
|---|---|---|
| mouseenter / mouseleave | No | No — only when entering/leaving the element itself |
| mouseover / mouseout | Yes | Yes — fires when moving between child elements |
contextmenu (Right-Click)
The contextmenu event fires when the user right-clicks (or uses the context menu key). You can prevent the default context menu with e.preventDefault().
const area = document.getElementById("editor");
area.addEventListener("contextmenu", (e) => {
e.preventDefault(); // block default browser menu
console.log("Right-click at", e.clientX, e.clientY);
console.log("Show custom context menu here");
});Event Coordinates
Mouse events carry several coordinate properties. Choosing the right one depends on whether you need coordinates relative to the viewport, the page, the screen, or the target element.
| Property | Relative To |
|---|---|
| clientX / clientY | The browser viewport (visible area) |
| pageX / pageY | The full document (includes scroll offset) |
| screenX / screenY | The physical monitor screen |
| offsetX / offsetY | The target element's padding edge |
document.addEventListener("click", (e) => {
console.log("clientX/Y:", e.clientX, e.clientY); // viewport
console.log("pageX/Y:", e.pageX, e.pageY); // document
console.log("screenX/Y:", e.screenX, e.screenY); // monitor
console.log("offsetX/Y:", e.offsetX, e.offsetY); // element
});