Start · Sprachen · JavaScript · Referenz · CaretPosition.getClientRect()

CaretPosition.getClientRect()

Methode

Gibt ein <code>DOMRect</code> mit Position und Größe des Caret-Bereichs relativ zum Viewport zurück, oder <code>null</code>, wenn kein Rechteck ermittelt werden kann.

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

Signatur

CaretPosition.prototype.getClientRect()

Beschreibung

Die Methode getClientRect() eines CaretPosition-Objekts liefert das Rechteck, das die Einfügemarke (den Caret) an dieser Position auf dem Bildschirm einnimmt. Die Koordinaten beziehen sich wie bei Element.getBoundingClientRect() auf den Viewport, nicht auf das Dokument. Da der Caret-Bereich zusammengefallen ist, hat das Rechteck typischerweise die Breite 0 und die Höhe der jeweiligen Textzeile.

Ein CaretPosition-Objekt erhältst du in der Regel über document.caretPositionFromPoint(x, y). Zusammen mit offsetNode und offset kannst du so bestimmen, an welcher Textstelle ein Klick oder Mauszeiger liegt und wo genau diese Stelle gezeichnet wird.

Typische Einsatzzwecke sind eigene Caret-Anzeigen in Editoren, Tooltips oder Autovervollständigungs-Popups an der Textposition, Markierungswerkzeuge sowie Drag-and-Drop-Einfügemarken in Text.

Rückgabewert

Typ
DOMRect | null
Beschreibung
Ein DOMRect mit x, y, width, height, top, left, right und bottom in CSS-Pixeln relativ zum Viewport. null, wenn für die Caret-Position kein Rechteck berechnet werden kann (z. B. wenn der Knoten nicht gerendert wird).

Beispiele

Caret-Rechteck an der Klickposition ermitteln

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

  const rect = pos.getClientRect();
  if (!rect) {
    console.log('Kein Rechteck verfügbar');
    return;
  }

  console.log(`Knoten: ${pos.offsetNode.nodeName}, Offset: ${pos.offset}`);
  console.log(`Caret bei x=${rect.left.toFixed(1)}, y=${rect.top.toFixed(1)}, Höhe=${rect.height.toFixed(1)}`);
});
Knoten: #text, Offset: 17 Caret bei x=243.5, y=112.0, Höhe=19.0

Eigenen Caret-Marker an der Mausposition zeichnen

const marker = document.createElement('div');
Object.assign(marker.style, {
  position: 'absolute',
  width: '2px',
  background: 'crimson',
  pointerEvents: 'none'
});
document.body.append(marker);

document.addEventListener('mousemove', ({ clientX, clientY }) => {
  const rect = document.caretPositionFromPoint?.(clientX, clientY)?.getClientRect();
  if (!rect) {
    marker.hidden = true;
    return;
  }
  marker.hidden = false;
  // Viewport-Koordinaten in Dokument-Koordinaten umrechnen
  marker.style.left = `${rect.left + window.scrollX}px`;
  marker.style.top = `${rect.top + window.scrollY}px`;
  marker.style.height = `${rect.height}px`;
});

Browserübergreifend mit Fallback auf caretRangeFromPoint

const getCaretRect = (x, y) => {
  if (document.caretPositionFromPoint) {
    return document.caretPositionFromPoint(x, y)?.getClientRect() ?? null;
  }
  // Älteres WebKit/Blink: Range statt CaretPosition
  if (document.caretRangeFromPoint) {
    return document.caretRangeFromPoint(x, y)?.getBoundingClientRect() ?? null;
  }
  return null;
};

document.addEventListener('dblclick', (e) => {
  const rect = getCaretRect(e.clientX, e.clientY);
  console.log(rect ? `Top: ${Math.round(rect.top)}px` : 'nicht unterstützt');
});
Top: 112px

// Wichtig · Fallstricke

  • Viewport-Koordinaten: Die Werte ändern sich beim Scrollen. Für absolut positionierte Elemente musst du window.scrollX/window.scrollY addieren.
  • Rückgabewert kann null sein: Prüfe immer vorher, z. B. mit optionaler Verkettung (?.). Auch caretPositionFromPoint() selbst kann null liefern, etwa außerhalb des Viewports.
  • Breite meist 0: Das Rechteck steht für eine zusammengefallene Position, nicht für ein Zeichen. Willst du die Zeichenbreite wissen, nimm eine Range über ein Zeichen und getBoundingClientRect().
  • Formularfelder: In <input> und <textarea> verhalten sich offsetNode und das Rechteck je nach Browser unterschiedlich. Teste das deshalb gezielt.
  • Kompatibilität: Firefox unterstützt caretPositionFromPoint() samt getClientRect() schon lange, Chromium-Browser erst ab Version 128. In Safari fehlt die Unterstützung je nach Version, dort steht nur das nicht standardisierte document.caretRangeFromPoint() zur Verfügung. Nutze eine Funktionserkennung mit Fallback.
  • Die Methode ist schreibgeschützt und hat keine Nebenwirkungen. Bei vielen Aufrufen (z. B. in mousemove) wird aber jedes Mal das Layout berechnet. Drossle solche Aufrufe gegebenenfalls mit requestAnimationFrame.