Click and Hover Handlers
Click and hover interactions are some of the first events you will use in the browser.
They are common in buttons, menus, cards, tooltips, navigation, and interactive lists.
Click Handlers
Use a click listener when the user activates an element with a mouse, trackpad,
touch, or keyboard.
<button id="menu-button">Open menu</button>
<nav id="menu" hidden>...</nav>const button = document.querySelector("#menu-button");
const menu = document.querySelector("#menu");
button.addEventListener("click", () => {
menu.hidden = !menu.hidden;
});For real buttons, prefer the <button> element. It already supports keyboard
activation and communicates its purpose to assistive technologies.
Reading Click Information
The event object can tell you where the click happened.
document.addEventListener("click", (event) => {
console.log(event.clientX, event.clientY);
});Useful mouse event properties:
| Property | Meaning |
|---|---|
clientX / clientY |
position inside the viewport |
pageX / pageY |
position on the page |
button |
which mouse button was used |
altKey, ctrlKey, shiftKey, metaKey |
modifier keys |
Hover Handlers
Hover behavior is often built with mouseenter and mouseleave.
const card = document.querySelector(".product-card");
card.addEventListener("mouseenter", () => {
card.classList.add("is-active");
});
card.addEventListener("mouseleave", () => {
card.classList.remove("is-active");
});Use CSS :hover for purely visual effects when possible.
.product-card:hover {
border-color: blue;
}Use JavaScript hover handlers when behavior needs logic, state, timing, or communication with other parts of the page.
mouseover vs mouseenter
mouseover bubbles.
mouseenter does not bubble.
That means mouseover can fire when moving between child elements inside the
same parent.
card.addEventListener("mouseover", () => {
console.log("Pointer moved over card or one of its children");
});
card.addEventListener("mouseenter", () => {
console.log("Pointer entered the card boundary");
});For simple hover behavior on one element, mouseenter and mouseleave are
usually easier to reason about.
Pointer Events for Modern Input
Mouse events do not fully describe touch and stylus input.
Pointer events are designed for multiple input types.
button.addEventListener("pointerenter", () => {
button.classList.add("is-hovered");
});
button.addEventListener("pointerleave", () => {
button.classList.remove("is-hovered");
});For components that should work across devices, consider pointer events.
Accessibility Considerations
Do not make important behavior available only on hover.
Some users:
- navigate with a keyboard
- use touch screens where hover does not exist
- use assistive technology
- have motor impairments
If hover shows important information, make it available through focus or click too.
const help = document.querySelector("#help");
const tooltip = document.querySelector("#tooltip");
function showTooltip() {
tooltip.hidden = false;
}
function hideTooltip() {
tooltip.hidden = true;
}
help.addEventListener("mouseenter", showTooltip);
help.addEventListener("mouseleave", hideTooltip);
help.addEventListener("focus", showTooltip);
help.addEventListener("blur", hideTooltip);Common Mistakes
Using a div as a button without keyboard support:
<div id="save">Save</div>Prefer:
<button id="save">Save</button>Putting critical content behind hover only:
If the user cannot hover, they may never discover the content.Doing heavy work on mousemove:
document.addEventListener("mousemove", () => {
// This can run many times per second.
});Summary
Click handlers are used for activation. Hover handlers are used for pointer presence.
Use semantic elements, support keyboard and touch users, and prefer CSS for simple visual hover effects.