Signatur
Beschreibung
Das Ereignis contextmenu wird an einem Element ausgelöst, bevor der Browser sein eingebautes Kontextmenü anzeigt. Meist geschieht das per Rechtsklick. Es kann aber auch über die Kontextmenü-Taste der Tastatur, Umschalt+F10 oder langes Drücken auf Touch-Geräten kommen. Das Ereignisobjekt ist ein PointerEvent (in älteren Browsern ein MouseEvent). Es enthält also Koordinaten wie clientX/clientY sowie Zusatztasten wie shiftKey oder ctrlKey.
Ruft man event.preventDefault() auf, zeigt der Browser sein Standardmenü nicht an. So baut man eigene Kontextmenüs, zum Beispiel in Dateimanagern, Editoren, Tabellen oder Spielen. Das Ereignis steigt durch den DOM-Baum auf (Bubbling) und lässt sich abbrechen (cancelable). Deshalb eignet es sich gut für Ereignisdelegation an einem gemeinsamen Elternelement.
Man registriert einen Handler entweder mit addEventListener("contextmenu", handler) oder über die Eigenschaft element.oncontextmenu = handler. Mit addEventListener sind mehrere Handler möglich, die sich mit removeEventListener gezielt wieder entfernen lassen. Die on-Eigenschaft nimmt dagegen immer nur einen Handler auf.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "contextmenu". |
|
| $handler Pflicht | (event: PointerEvent) => void | Callback, der das Ereignisobjekt erhält. Es liefert unter anderem clientX, clientY, pageX, pageY, button (meist 2), target und preventDefault(). |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie capture, once, passive oder signal. Achtung: Mit passive: true wirkt preventDefault() nicht. |
Rückgabewert
addEventListener gibt nichts zurück. Gibt man mit preventDefault() das Ereignis ab (bzw. mit return false bei oncontextmenu), erscheint das Standardmenü des Browsers nicht.Beispiele
Eigenes Kontextmenü an der Mausposition anzeigen
const area = document.querySelector('#arbeitsflaeche');
const menu = document.querySelector('#kontextmenue'); // <ul hidden> mit position: fixed im CSS
area.addEventListener('contextmenu', (event) => {
event.preventDefault(); // Browser-Menü unterdrücken
menu.style.left = `${event.clientX}px`;
menu.style.top = `${event.clientY}px`;
menu.hidden = false;
});
// Menü bei Klick irgendwo oder Escape schließen
document.addEventListener('click', () => { menu.hidden = true; });
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') menu.hidden = true;
});
Ereignisdelegation: Zeile in einer Tabelle erkennen
const table = document.querySelector('#dateien');
table.addEventListener('contextmenu', (event) => {
const row = event.target.closest('tr[data-id]');
if (!row) return; // außerhalb einer Zeile: Standardmenü zulassen
event.preventDefault();
console.log(`Kontextmenü für Datei ${row.dataset.id} bei (${event.clientX}, ${event.clientY})`);
});
Handler wieder entfernen und oncontextmenu-Variante
const canvas = document.querySelector('canvas');
const blockMenu = (event) => event.preventDefault();
canvas.addEventListener('contextmenu', blockMenu);
// Später, z. B. nach Spielende: Standardmenü wieder erlauben
const stopGame = () => {
canvas.removeEventListener('contextmenu', blockMenu);
console.log('Kontextmenü wieder aktiv');
};
// Alternative über die on-Eigenschaft (nur ein Handler möglich)
const img = document.querySelector('img.vorschau');
img.oncontextmenu = (event) => {
event.preventDefault();
console.log('Rechtsklick auf', img.alt);
};
// Entfernen:
// img.oncontextmenu = null;
stopGame();
Mit AbortController mehrere Listener gleichzeitig abmelden
const controller = new AbortController();
const editor = document.querySelector('#editor');
editor.addEventListener('contextmenu', (event) => {
event.preventDefault();
console.log('Editor-Menü');
}, { signal: controller.signal });
// Beim Zerstören der Komponente alle Listener auf einmal entfernen
controller.abort();
// Wichtig · Fallstricke
- Barrierefreiheit: Wer das Standardmenü unterdrückt, nimmt Nutzern Funktionen wie „Link in neuem Tab öffnen“, „Kopieren“ oder die Rechtschreibprüfung weg. Unterdrücken Sie das Menü nur gezielt. Eigene Menüs sollten per Tastatur bedienbar sein (Pfeiltasten, Escape) und passende ARIA-Rollen tragen (
role="menu",role="menuitem"). - Kein Schutz für Inhalte: Ein blockierter Rechtsklick schützt weder Bilder noch Text. Entwicklerwerkzeuge, der Quelltext und Screenshots bleiben ja verfügbar.
- Firefox: Hält der Nutzer
Umschaltgedrückt, zeigt Firefox trotzpreventDefault()das Standardmenü an. Außerdem lässt sich die Optiondom.event.contextmenu.enabledabschalten; dann kann eine Seite das Menü gar nicht unterdrücken. - Tastatur-Auslösung: Öffnet man das Menü per Taste, können
clientX/clientYje nach Browser0sein oder auf das fokussierte Element zeigen. Positionieren Sie Ihr Menü in diesem Fall amevent.target, zum Beispiel mitgetBoundingClientRect(). - macOS:
Strg+Klicklöst ebenfallscontextmenuaus, und zwar mitbutton === 0. - Touch-Geräte: Langes Drücken löst das Ereignis auf Android aus, auf iOS Safari teils nicht zuverlässig. Dort braucht man eventuell eine eigene Erkennung für langes Drücken über Pointer-Events.
- Reihenfolge: Bei einem Rechtsklick kommt meist erst
mousedown(button 2), danncontextmenuund dannmouseup. Unter Windows feuertcontextmenuerst nachmouseup. Verlassen Sie sich also nicht auf eine feste Reihenfolge. - Das Attribut
contextmenuund das Element<menu type="context">sind veraltet und wurden aus allen Browsern entfernt. Verwenden Sie stattdessen dieses Ereignis.