A web page cannot add arbitrary commands to the browser’s native context menu across browsers. The portable approach is to cancel the contextmenu event and show an HTML menu at the pointer position.
Last updated: October 15, 2026.
<button id="actions" aria-haspopup="menu">Actions</button>
<div id="menu" role="menu" hidden>
<button role="menuitem">Copy reference</button>
<button role="menuitem">Open details</button>
</div>
<script>
const menu = document.querySelector('#menu');
document.addEventListener('contextmenu', event => {
event.preventDefault();
menu.hidden = false;
const left = Math.min(event.clientX, innerWidth - menu.offsetWidth - 8);
const top = Math.min(event.clientY, innerHeight - menu.offsetHeight - 8);
Object.assign(menu.style, { position: 'fixed', left: left + 'px', top: top + 'px' });
menu.querySelector('[role="menuitem"]').focus();
});
document.addEventListener('click', () => { menu.hidden = true; });
document.addEventListener('keydown', event => {
if (event.key === 'Escape') menu.hidden = true;
});
</script>Measure the menu after revealing it, then clamp its coordinates to the viewport. The visible Actions button gives keyboard and touch users another way to reach the same commands.
Know what the browser exposes
MDN documents the contextmenu event and preventDefault(). It does not provide a cross-browser API for inserting page-defined items into the browser menu. Firefox can also show its native menu when the user holds Shift, so do not treat suppression as a security control.
Attach the handler only to the application area that needs contextual actions. Replacing right-click everywhere removes useful browser commands and surprises users.
Complete the interaction model
The W3C menu button pattern calls for Enter or Space to open the menu, focus to move into it, arrow keys to move between items, and Escape to close it. A production menu should implement those keys, return focus to its opener, close on outside click and scroll, and keep actions available through a normal button.
Use position: fixed with clientX and clientY, or use absolute positioning with page coordinates consistently. Recalculate after content changes. Continue with toggling menus with classes, accessible JavaScript tabs, and attribute-driven CSS state.