Signatur
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
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)}`);
});
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');
});
// Wichtig · Fallstricke
- Viewport-Koordinaten: Die Werte ändern sich beim Scrollen. Für absolut positionierte Elemente musst du
window.scrollX/window.scrollYaddieren. - Rückgabewert kann
nullsein: Prüfe immer vorher, z. B. mit optionaler Verkettung (?.). AuchcaretPositionFromPoint()selbst kannnullliefern, 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 undgetBoundingClientRect(). - Formularfelder: In
<input>und<textarea>verhalten sichoffsetNodeund das Rechteck je nach Browser unterschiedlich. Teste das deshalb gezielt. - Kompatibilität: Firefox unterstützt
caretPositionFromPoint()samtgetClientRect()schon lange, Chromium-Browser erst ab Version 128. In Safari fehlt die Unterstützung je nach Version, dort steht nur das nicht standardisiertedocument.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 mitrequestAnimationFrame.