mouse-only-event-handlers

Pointer-only event handlers should have a keyboard-reachable equivalent

manualWCAG 2.1.1, 2.1.3 (AAA)confidence: lowseverity: moderateoperable

Flags elements with a pointer-only event handler (onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, onmousemove, onmouseenter, onmouseleave), inline or, with the listener hook, added from script, and no keyboard-reachable equivalent (onkeydown/onkeyup/onkeypress/onfocus/onblur), for manual review.

Applies to. Elements carrying at least one inline pointer-only event-handler attribute (onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, onmousemove, onmouseenter, onmouseleave) with a non-empty value, or, where the page runs the listener hook (listenerHookScript), a listener of one of those types added from script (addEventListener or the on… property), that are also eligible/reachable (not hidden/aria-hidden/display:none).

Expectation. The element also carries at least one keyboard-reachable inline handler: onkeydown, onkeyup, onkeypress (the direct keyboard- event equivalents), or onfocus/onblur (the standard substitute for hover-triggered behavior: focus/blur are the keyboard- navigable analog to mouseover/mouseout, per WCAG technique G90). A handler is reachable only if keyboard events can reach it: onfocus/onblur when the element itself can take focus, and a key handler when the element or one of its descendants can (key events bubble, focus events do not). Otherwise the element's mouse-driven behavior (a hover tooltip, a custom dropdown, a drag interaction) has no way to be triggered by a keyboard-only user, and it is flagged with a reason saying whether the keyboard handlers are missing or cannot run. With the listener hook, a key, focus or blur listener added from script on the element counts as the matching inline handler does, and so do focusin/focusout listeners, which, like key events, also fire for a focused descendant.

What a finding reports.

  • mouseAttrs: the pointer-only handlers the element has. One item is an attribute name, such as onmouseover; a listener added from script is named as the attribute of its type.
  • keyboardAttrs (handlers that cannot run, MOUSE_ONLY_HANDLER_KEYBOARD_EQUIVALENT_NOT_FOCUSABLE): the keyboard handler attributes the element carries, which keyboard events cannot reach. One item is an attribute name, such as onfocus.

These data.details fields help to read and reproduce a finding. Apart from reasonCode and the few fields Output schema names as stable, they are not a stable contract: a field may be renamed or dropped in a minor release, so don’t build on them.

Examples

can't tell
<div onmouseover="show()" onmouseout="hide()">Hover-only tooltip trigger</div>

onmouseover/onmouseout have no onfocus/onblur counterpart, so a keyboard user can never trigger this behavior.

can't tell
<div onmouseover="show()" onfocus="show()">Menu</div>

The onfocus handler never runs: the <div> cannot take focus.

n/a
<div onmouseover="show()" onmouseout="hide()" onfocus="show()" onblur="hide()" tabindex="0">Hover + focus pair</div>

Each mouse handler is paired with a keyboard-equivalent focus handler.

How to check

When this rule can’t decide, it reports cantTell and leaves the question to a person. Each question it can ask is listed here under its reason code, with the steps to answer it. A finding carries the same steps as howToCheck, in the scan’s language. See Output schema.

MOUSE_ONLY_HANDLER_KEYBOARD_EQUIVALENT_NOT_FOCUSABLE

  1. Find the element the report names and note what its mouse handlers do by hovering or clicking it.
  2. Press Tab through that part of the page and watch whether focus ever lands on the element or on something inside it.
  3. If it does, try Enter, Space and the arrow keys and compare with what the mouse did.
  4. If the keyboard can't do it here, check whether what the mouse does can be done another way with the keyboard alone, for example with a button or menu item elsewhere on the page. It only counts if it does everything the mouse does.

Pass. The element (or something inside it) gets keyboard focus and its key or focus handlers give the same result as the mouse, or what the mouse does can be done another way with the keyboard alone, or the mouse action is only visual.

Fail. Focus never reaches the element and what the mouse does cannot be done another way with the keyboard, which fails WCAG 2.1.1 (F54).

MOUSE_ONLY_HANDLER_NO_KEYBOARD_EQUIVALENT

  1. Find the element the report names and note its mouse handlers (such as onmouseover or ondblclick).
  2. Hover, click or double-click it with the mouse and note what happens (a menu opens, a tooltip shows, an item moves).
  3. Reload, then use only the keyboard: Tab to the element (or the control around it) and try Enter, Space, the arrow keys and Escape.
  4. Check whether the same result happens, or whether the same function is offered by another control a keyboard can reach.

Pass. The mouse action only adds a visual effect, or the keyboard gets the same result on focus or with a key.

Fail. Something the mouse does (opening a menu, showing information, moving an item) cannot be done with the keyboard, which fails WCAG 2.1.1 (F54).

View source