Signatur
Beschreibung
getClientRects() liefert die Rechtecke aller Border-Boxen, die ein Element beim Rendern erzeugt. Bei den meisten Block-Elementen ist das genau ein Rechteck. Inline-Elemente wie <span> oder <a>, die über mehrere Zeilen umbrechen, erzeugen dagegen ein Rechteck pro Zeilenfragment. Das passiert auch bei Elementen, die über mehrere Spalten oder Seiten verteilt sind.
Die Koordinaten (x, y, top, left, right, bottom, width, height) beziehen sich auf den Viewport, also den sichtbaren Bereich des Fensters. Sie ändern sich beim Scrollen. Für Dokumentkoordinaten addiert man window.scrollX bzw. window.scrollY.
Typische Einsatzfälle sind: Markierungen oder Tooltips an genau der Zeile eines umbrochenen Links platzieren, Textauswahlen hervorheben und die tatsächlich gerenderte Geometrie von Inline-Inhalten messen. Wenn du nur das umschließende Gesamtrechteck brauchst, ist getBoundingClientRect() einfacher. Es gibt die Vereinigung aller Rechtecke aus getClientRects() zurück.
Rückgabewert
DOMRect-Objekten, eines pro Border-Box. Die Liste ist leer, wenn das Element keine Box erzeugt (z. B. display: none oder nicht im Dokument eingehängt).Beispiele
Zeilenfragmente eines umbrochenen Links zählen
// HTML: <p style="width:150px"><a id="link" href="#">Ein ziemlich langer Linktext, der umbricht</a></p>
const link = document.getElementById('link');
const rects = link.getClientRects();
console.log(`Anzahl Zeilen: ${rects.length}`);
for (const rect of rects) {
console.log(`top=${Math.round(rect.top)} left=${Math.round(rect.left)} breite=${Math.round(rect.width)}`);
}
Jede Zeile eines Inline-Elements hervorheben
const highlightLines = (element) => {
// Alte Markierungen entfernen
document.querySelectorAll('.line-marker').forEach((m) => m.remove());
for (const rect of element.getClientRects()) {
const marker = document.createElement('div');
marker.className = 'line-marker';
Object.assign(marker.style, {
position: 'absolute',
// Viewport- in Dokumentkoordinaten umrechnen
top: `${rect.top + window.scrollY}px`,
left: `${rect.left + window.scrollX}px`,
width: `${rect.width}px`,
height: `${rect.height}px`,
background: 'rgba(255, 220, 0, 0.4)',
pointerEvents: 'none'
});
document.body.append(marker);
}
};
highlightLines(document.querySelector('p span.wichtig'));
Tooltip am letzten Zeilenfragment ausrichten
const showTooltipAtEnd = (anchor, text) => {
const rects = anchor.getClientRects();
if (rects.length === 0) return; // Element nicht gerendert
const last = rects[rects.length - 1];
const tip = document.createElement('div');
tip.textContent = text;
tip.style.position = 'fixed'; // fixed => Viewport-Koordinaten direkt nutzbar
tip.style.top = `${last.bottom + 4}px`;
tip.style.left = `${last.right}px`;
document.body.append(tip);
};
showTooltipAtEnd(document.querySelector('a.mehr'), 'Weiterlesen');
Vergleich mit getBoundingClientRect()
const span = document.querySelector('span');
const rects = [...span.getClientRects()];
const bounding = span.getBoundingClientRect();
const unionLeft = Math.min(...rects.map((r) => r.left));
console.log(rects.length, unionLeft === bounding.left);
// Wichtig · Fallstricke
- Viewport-relativ: Die Werte ändern sich beim Scrollen. Für absolute Positionierung musst du
window.scrollX/scrollYaddieren. Fürposition: fixedkannst du sie direkt verwenden. - Kein Array:
DOMRectListhat wedermapnochfilter. Wandle sie vorher mit[...rects]oderArray.from(rects)um. Die Liste ist eine Momentaufnahme und aktualisiert sich nicht von selbst. - Leere Liste: Bei
display: none, nicht eingehängten Elementen und Elementen ohne Layout-Box istlengthgleich0. Prüfe das vor dem Zugriff aufrects[0]. - Tabellen: Bei Tabellen-Elementen mit Beschriftung (
<caption>) enthält die Liste auch die Box der Beschriftung. - Transformationen: CSS-
transformwird berücksichtigt. Die Rechtecke sind dann die achsenparallelen Hüllen der transformierten Boxen. - Performance: Der Aufruf erzwingt ein synchrones Layout (Reflow). Vermeide es, in Schleifen abwechselnd DOM-Änderungen zu schreiben und Rechtecke zu lesen („Layout Thrashing“).
- Kompatibilität: Wird von allen modernen Browsern unterstützt. Ältere Versionen des Internet Explorer lieferten abweichende Werte (z. B. ohne
width/height).