Start · Sprachen · JavaScript · Referenz · Document.caretPositionFromPoint()

Document.caretPositionFromPoint()

Methode

Gibt ein <code>CaretPosition</code>-Objekt mit dem DOM-Knoten und dem Zeichenoffset der Einfügemarke an den angegebenen Viewport-Koordinaten zurück.

seit JavaScript Firefox 20+, Chrome/Edge 128+; in Safari erst in n Kategorie: webapi

Signatur

Document.prototype.caretPositionFromPoint(x, y, options)

Beschreibung

document.caretPositionFromPoint() findet heraus, wo genau im Text die Einfügemarke (der Caret) stehen würde, wenn der Nutzer an die Bildschirmkoordinaten (x, y) klickt. Zurück kommt ein CaretPosition-Objekt mit offsetNode (meist ein Textknoten), offset (Zeichenposition innerhalb dieses Knotens) und der Methode getClientRect(), die das Rechteck des Carets liefert.

Typische Einsatzfälle sind eigene Editoren, Drag-and-drop von Text an eine bestimmte Stelle, das Ermitteln des Wortes unter dem Mauszeiger (z. B. für Wörterbuch- oder Übersetzungs-Tooltips), das Platzieren von Markierungen und Kommentaren sowie das Anlegen einer Selektion ab einem Mausklick.

Die Koordinaten beziehen sich auf den Viewport – also dieselben Werte wie MouseEvent.clientX/clientY, nicht pageX/pageY. Ist der Knoten ein Textknoten, ist offset ein Zeichenindex; bei einem Elementknoten ist es der Index des Kindknotens. Liegt der Punkt außerhalb des Viewports oder lässt sich keine Position ermitteln, wird null zurückgegeben.

Über den optionalen Parameter options.shadowRoots kann man Shadow-Roots übergeben, in die hinein die Suche erfolgen darf. Ohne diese Angabe wird eine Position in einem Shadow-DOM auf den Host-Knoten zurückgeführt.

Parameter

Name Typ Default Beschreibung
$x Pflicht number Horizontale Koordinate in CSS-Pixeln, relativ zum Viewport (entspricht clientX).
$y Pflicht number Vertikale Koordinate in CSS-Pixeln, relativ zum Viewport (entspricht clientY).
$options { shadowRoots?: ShadowRoot[] } {} Optionales Objekt. shadowRoots ist ein Array von ShadowRoot-Objekten, in deren Inhalt die Caret-Position ermittelt werden darf (auch geschlossene Shadow-Roots, sofern man eine Referenz besitzt). Neuere Ergänzung, nicht überall unterstützt.

Rückgabewert

Typ
CaretPosition | null
Beschreibung
Ein CaretPosition-Objekt mit offsetNode, offset und getClientRect() – oder null, wenn keine Position bestimmt werden kann (z. B. Punkt außerhalb des Viewports).

Beispiele

Klickposition im Text ermitteln

document.addEventListener('click', (event) => {
  const pos = document.caretPositionFromPoint(event.clientX, event.clientY);
  if (!pos) return;

  const { offsetNode, offset } = pos;
  if (offsetNode.nodeType === Node.TEXT_NODE) {
    const text = offsetNode.textContent;
    console.log(`Offset ${offset}:`, text.slice(0, offset) + '|' + text.slice(offset));
  }
});
Offset 6: Hallo |Welt

Browserübergreifender Helfer mit Fallback auf caretRangeFromPoint()

const getCaretAt = (x, y) => {
  if (typeof document.caretPositionFromPoint === 'function') {
    const pos = document.caretPositionFromPoint(x, y);
    return pos ? { node: pos.offsetNode, offset: pos.offset } : null;
  }
  // Fallback für ältere WebKit-/Blink-Versionen (nicht standardisiert)
  if (typeof document.caretRangeFromPoint === 'function') {
    const range = document.caretRangeFromPoint(x, y);
    return range ? { node: range.startContainer, offset: range.startOffset } : null;
  }
  return null;
};

document.addEventListener('dblclick', (e) => {
  console.log(getCaretAt(e.clientX, e.clientY));
});
{ node: #text "Lorem ipsum …", offset: 12 }

Wort unter dem Mauszeiger ermitteln

const wordAt = (x, y) => {
  const pos = document.caretPositionFromPoint(x, y);
  if (!pos || pos.offsetNode.nodeType !== Node.TEXT_NODE) return null;

  const text = pos.offsetNode.textContent;
  let start = pos.offset;
  let end = pos.offset;
  while (start > 0 && /\p{L}/u.test(text[start - 1])) start--;
  while (end < text.length && /\p{L}/u.test(text[end])) end++;
  return text.slice(start, end) || null;
};

const article = document.querySelector('article');
article.addEventListener('mousemove', (e) => {
  const word = wordAt(e.clientX, e.clientY);
  if (word) article.title = `Nachschlagen: ${word}`;
});
Tooltip: "Nachschlagen: Programmierung"

Marker an der Klickstelle einfügen und Caret-Rechteck auslesen

const editor = document.querySelector('#editor');

editor.addEventListener('click', (e) => {
  const pos = document.caretPositionFromPoint(e.clientX, e.clientY);
  if (!pos || !editor.contains(pos.offsetNode)) return;

  const range = document.createRange();
  range.setStart(pos.offsetNode, pos.offset);
  range.collapse(true);

  const marker = document.createElement('mark');
  marker.textContent = '★';
  range.insertNode(marker);

  const rect = pos.getClientRect();
  console.log('Caret bei', Math.round(rect.left), Math.round(rect.top));
});
Caret bei 184 92

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Firefox unterstützt die Methode schon lange, Chrome/Edge erst seit Version 128, Safari erst in neueren Versionen. Für ältere Browser gibt es das nicht standardisierte document.caretRangeFromPoint(), das einen Range zurückgibt – immer per Feature-Erkennung prüfen.
  • Koordinatensystem: Es werden Viewport-Koordinaten erwartet (clientX/clientY). Wer pageX/pageY übergibt, erhält auf gescrollten Seiten falsche Ergebnisse.
  • null prüfen: Liegt der Punkt außerhalb des Viewports oder über einem Bereich ohne Inhalt, ist das Ergebnis null.
  • Knotentyp beachten: offsetNode muss kein Textknoten sein. Bei Elementen ist offset ein Kindindex, kein Zeichenindex.
  • Formularfelder: Bei <input> und <textarea> hängt das Verhalten vom Browser ab: offsetNode kann das Element selbst sein, während der Offset sich auf den Wert des Feldes bezieht.
  • Shadow DOM: Ohne options.shadowRoots werden Positionen innerhalb von Shadow-Bäumen auf den Host zurückgeführt. Der Parameter options ist neuer als die Methode selbst.
  • Leistung: Der Aufruf löst eine Layout-Berechnung aus. In mousemove-Handlern besser drosseln, z. B. mit requestAnimationFrame().