Signatur
Beschreibung
document.elementFromPoint(x, y) führt einen „Hit-Test“ aus: Die Methode ermittelt, welches Element an einem bestimmten Punkt des sichtbaren Bereichs (Viewport) ganz oben liegt, also das Element, das ein Mausklick an dieser Stelle treffen würde. Die Koordinaten beziehen sich auf die linke obere Ecke des Viewports und nicht auf das Dokument. Sie entsprechen damit clientX/clientY eines Maus- oder Touch-Ereignisses.
Typische Einsatzfälle sind eigene Drag-and-Drop-Lösungen (Welches Element liegt unter dem gezogenen Objekt?), Touch-Gesten, bei denen touchmove immer das Startelement als target meldet, Hilfsmittel wie „Element untersuchen“-Overlays und Tests, ob ein Element tatsächlich sichtbar ist und nicht von einem anderen verdeckt wird.
Elemente mit pointer-events: none werden übersprungen, das Element darunter wird zurückgegeben. Liegt der Punkt in einem <iframe>, erhältst du das iframe-Element selbst und nicht dessen Inhalt. Bei Shadow DOM liefert die Methode auf document den Shadow-Host. Für den Inhalt des Shadow Trees rufst du stattdessen shadowRoot.elementFromPoint() auf.
Möchtest du alle übereinanderliegenden Elemente an einem Punkt haben, verwende document.elementsFromPoint(). Diese Methode liefert ein Array, sortiert von oben nach unten.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $x Pflicht | number | Horizontale Koordinate in CSS-Pixeln, relativ zum linken Rand des Viewports. | |
| $y Pflicht | number | Vertikale Koordinate in CSS-Pixeln, relativ zum oberen Rand des Viewports. |
Rückgabewert
null.Beispiele
Element unter dem Mauszeiger ermitteln
document.addEventListener('click', (event) => {
const el = document.elementFromPoint(event.clientX, event.clientY);
console.log('Getroffen:', el?.tagName, el?.id);
});
Drop-Ziel beim Touch-Ziehen finden
const dragItem = document.querySelector('.drag-item');
dragItem.addEventListener('touchmove', (event) => {
const touch = event.touches[0];
// Das gezogene Element selbst ignorieren
dragItem.style.pointerEvents = 'none';
const below = document.elementFromPoint(touch.clientX, touch.clientY);
dragItem.style.pointerEvents = '';
document.querySelectorAll('.dropzone').forEach((z) => z.classList.remove('hover'));
below?.closest('.dropzone')?.classList.add('hover');
}, { passive: true });
Prüfen, ob ein Element verdeckt ist
const isElementVisibleAtCenter = (el) => {
const rect = el.getBoundingClientRect();
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
const hit = document.elementFromPoint(x, y);
// Sichtbar, wenn das Element selbst oder eines seiner Kinder getroffen wird
return hit !== null && (hit === el || el.contains(hit));
};
const btn = document.querySelector('#submit');
console.log(isElementVisibleAtCenter(btn));
Punkt außerhalb des Viewports
console.log(document.elementFromPoint(-10, -10));
console.log(document.elementFromPoint(window.innerWidth + 50, 10));
// Wichtig · Fallstricke
- Viewport- statt Seitenkoordinaten:
pageX/pageYenthalten den Scroll-Versatz und führen deshalb auf gescrollten Seiten zu falschen Treffern. VerwendeclientX/clientYoder rechnewindow.scrollX/scrollYheraus. - Nur sichtbarer Bereich: Punkte außerhalb des Viewports liefern
null. Elemente, die herausgescrollt sind, lassen sich so nicht finden. pointer-events: nonemacht Elemente für den Hit-Test unsichtbar. Das kannst du gezielt nutzen, etwa für das gezogene Element beim Drag and Drop. Es kann aber auch unerwartete Ergebnisse verursachen.- iframes und Shadow DOM: Die Methode geht nicht in iframes hinein, zurück kommt das
iframe-Element. Bei Shadow DOM bekommst du den Host, den inneren Knoten erhältst du übershadowRoot.elementFromPoint(). - Nur Elemente: Textknoten werden nie zurückgegeben. Für die genaue Textposition gibt es
document.caretPositionFromPoint()bzw.caretRangeFromPoint(). - Performance: Jeder Aufruf kann eine Layout-Berechnung (Reflow) auslösen. In
mousemove- oderscroll-Handlern solltest du die Aufrufe drosseln, z. B. mitrequestAnimationFrame. - Die Methode wird von allen modernen Browsern unterstützt, auch von sehr alten Versionen des Internet Explorers.