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

Document.caretRangeFromPoint()

Methode

Liefert ein zusammengeklapptes <code>Range</code>-Objekt an der Einfügemarken-Position (Caret) unter den angegebenen Viewport-Koordinaten oder <code>null</code>.

seit JavaScript Nicht standardisiert; Chrome, Edge, Safari, Opera Kategorie: webapi

Signatur

Document.prototype.caretRangeFromPoint(x, y)

Beschreibung

document.caretRangeFromPoint() ermittelt, an welcher Stelle im Textfluss eine Einfügemarke (Caret) läge, wenn man an den übergebenen Koordinaten klicken würde. Das Ergebnis ist ein zusammengeklapptes Range-Objekt: startContainer und endContainer sind identisch (meist ein Textknoten), ebenso startOffset und endOffset, also die Zeichenposition innerhalb dieses Knotens.

Typische Anwendungsfälle sind Editoren, die beim Ablegen per Drag & Drop die Einfügeposition bestimmen müssen, Wörterbuch- oder Übersetzungs-Tooltips, die das Wort unter dem Mauszeiger ermitteln, sowie eigene Markierungs- und Annotationswerkzeuge. Die Koordinaten beziehen sich auf den Viewport (wie clientX/clientY eines MouseEvent), nicht auf das gesamte Dokument.

Die Methode ist eine WebKit-/Blink-Erweiterung und nicht Teil eines Standards. Das standardisierte Gegenstück ist document.caretPositionFromPoint(), das ein CaretPosition-Objekt mit offsetNode und offset zurückgibt. Für browserübergreifenden Code sollte man zuerst auf die Standardmethode prüfen und caretRangeFromPoint() nur als Rückfall verwenden.

Parameter

Name Typ Default Beschreibung
$x Pflicht number Horizontale Koordinate in CSS-Pixeln relativ zum Viewport (z. B. event.clientX).
$y Pflicht number Vertikale Koordinate in CSS-Pixeln relativ zum Viewport (z. B. event.clientY).

Rückgabewert

Typ
Range | null
Beschreibung
Ein zusammengeklapptes Range-Objekt an der Caret-Position oder null, wenn die Koordinaten außerhalb des Viewports liegen oder dort kein passender Knoten gefunden wird.

Beispiele

Zeichenposition beim Klick ermitteln

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

  const node = range.startContainer;
  console.log('Knoten:', node.nodeName, '| Offset:', range.startOffset);
});
Knoten: #text | Offset: 17

Browserübergreifende Hilfsfunktion mit Fallback

const getCaretAt = (x, y) => {
  // Standardmethode bevorzugen (Firefox, neuere Chrome/Safari)
  if (document.caretPositionFromPoint) {
    const pos = document.caretPositionFromPoint(x, y);
    return pos ? { node: pos.offsetNode, offset: pos.offset } : null;
  }
  // WebKit/Blink-Fallback
  if (document.caretRangeFromPoint) {
    const range = document.caretRangeFromPoint(x, y);
    return range ? { node: range.startContainer, offset: range.startOffset } : null;
  }
  return null;
};

document.addEventListener('mouseup', (e) => {
  console.log(getCaretAt(e.clientX, e.clientY));
});
{ node: #text, offset: 42 }

Wort unter dem Mauszeiger hervorheben

const article = document.querySelector('article');

article.addEventListener('dblclick', (event) => {
  const range = document.caretRangeFromPoint(event.clientX, event.clientY);
  if (!range || range.startContainer.nodeType !== Node.TEXT_NODE) return;

  const text = range.startContainer.textContent;
  let start = range.startOffset;
  let end = range.startOffset;

  // Wortgrenzen suchen
  while (start > 0 && /\w/.test(text[start - 1])) start--;
  while (end < text.length && /\w/.test(text[end])) end++;

  range.setStart(range.startContainer, start);
  range.setEnd(range.startContainer, end);

  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  console.log('Wort:', range.toString());
});
Wort: JavaScript

Einfügeposition beim Drop in einen Editor

const editor = document.querySelector('[contenteditable]');

editor.addEventListener('dragover', (e) => e.preventDefault());

editor.addEventListener('drop', (e) => {
  e.preventDefault();
  const range = document.caretRangeFromPoint(e.clientX, e.clientY);
  if (!range) return;

  const text = e.dataTransfer.getData('text/plain');
  range.insertNode(document.createTextNode(text));
});

// Wichtig · Fallstricke

  • Nicht standardisiert: Firefox unterstützt caretRangeFromPoint() nicht. Verwende Feature-Erkennung und bevorzuge document.caretPositionFromPoint() (Standard, inzwischen auch in Chrome 128+ und Safari verfügbar).
  • Viewport-Koordinaten: Übergib clientX/clientY, nicht pageX/pageY – sonst liefert die Methode bei gescrollten Seiten falsche Ergebnisse oder null.
  • Liegen die Koordinaten außerhalb des sichtbaren Bereichs, ist der Rückgabewert null – immer prüfen.
  • Der startContainer ist nicht zwingend ein Textknoten; bei Bildern, leeren Elementen oder Formularfeldern kann es ein Element sein. Innerhalb von <input>/<textarea> ist das Verhalten uneinheitlich.
  • Elemente mit pointer-events: none oder user-select: none können das Ergebnis beeinflussen; Inhalte in Shadow-DOM werden je nach Browser nicht aufgelöst.
  • Bei häufigem Aufruf (z. B. in mousemove) Layout-Neuberechnungen bedenken und ggf. per requestAnimationFrame drosseln.