v144 · user input · demo
Hover Menu
A real-world nav dropdown: hovering a trigger appends a <ul> to the DOM;
moving away removes it entirely. Chrome 144 ensures pointerleave fires on the
correct ancestor even when the dropdown vanishes mid-hover — watch the event log below to see
boundary events flowing in the right order.
Boundary events now fire on nearest attached ancestor (Chrome 144+)
- Hover a menu item to see events…
what Chrome 144 fixes
Prior to Chrome 144, removing a child element from the DOM mid-hover could swallow or misroute
pointerleave events. In a conditional-render dropdown pattern the dropdown is
appended on hover and removed on leave — exactly the sequence that triggered the bug.
After Chrome 144, the browser re-evaluates the hover chain after each DOM mutation and dispatches
boundary events to the correct nearest still-attached ancestor, matching Safari and Firefox.
the pattern
// trigger: insert dropdown into DOM on hover
trigger.addEventListener('pointerenter', () => {
const ul = buildDropdown(items);
menuItem.appendChild(ul);
dropdownEl = ul;
});
// trigger: schedule removal on leave
trigger.addEventListener('pointerleave', () => {
removeTimer = setTimeout(maybeRemove, 50);
});
// dropdown: cancel removal while inside
dropdown.addEventListener('pointerenter', () => {
clearTimeout(removeTimer);
});
// dropdown: schedule removal when leaving it too
dropdown.addEventListener('pointerleave', () => {
removeTimer = setTimeout(maybeRemove, 50);
});
// Chrome 144: pointerleave fires on .menu-item even
// after the dropdown child is removed from the DOM.