Signatur
Beschreibung
Die schreibgeschützte Eigenschaft offsetWidth liefert die Layout-Breite eines Elements in CSS-Pixeln. Darin enthalten sind Inhaltsbreite, padding links und rechts, border links und rechts sowie eine eventuell vorhandene vertikale Scrollleiste. Nicht enthalten sind margin und Pseudo-Elemente wie ::before oder ::after.
Der Wert wird immer auf eine Ganzzahl gerundet. Wenn du die Breite mit Nachkommastellen brauchst, etwa für pixelgenaue Positionierung, verwende getBoundingClientRect().width. Hat das Element keine Layout-Box, weil es selbst oder ein Vorfahre display: none hat oder weil es nicht im Dokument eingehängt ist, ist der Wert 0.
Typische Einsatzfälle sind die Größenmessung für eigene Layout-Logik (z. B. Tooltips, Slider, Textkürzung) und die Prüfung, ob ein Element überhaupt dargestellt wird. offsetWidth bezieht sich auf das Layout und nicht auf die Darstellung: CSS-Transformationen wie transform: scale(2) ändern den Wert nicht, getBoundingClientRect() berücksichtigt sie dagegen.
Wichtig für die Leistung: Das Lesen von offsetWidth erzwingt eine synchrone Layout-Berechnung (Reflow), wenn seit der letzten Berechnung Styles oder das DOM geändert wurden. In Schleifen solltest du deshalb zuerst alle Werte lesen und erst danach schreiben.
Rückgabewert
0, wenn das Element keine Layout-Box hat.Beispiele
Breite mit Padding und Rahmen messen
const box = document.createElement('div');
box.style.cssText = 'width: 200px; padding: 10px; border: 5px solid #333; margin: 20px; box-sizing: content-box;';
document.body.append(box);
// 200 + 2*10 (Padding) + 2*5 (Rahmen); die Margin zählt nicht mit
console.log(box.offsetWidth);
console.log(box.clientWidth); // ohne Rahmen
Prüfen, ob ein Element sichtbar gerendert wird
const isRendered = (el) => el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
const menu = document.querySelector('#menu');
menu.style.display = 'none';
console.log(isRendered(menu));
menu.style.display = 'block';
console.log(isRendered(menu));
Ganzzahl vs. exakte Breite
const el = document.createElement('span');
el.style.cssText = 'display: inline-block; width: 100.6px;';
document.body.append(el);
console.log(el.offsetWidth); // gerundet
console.log(el.getBoundingClientRect().width); // exakt
el.style.transform = 'scale(2)';
console.log(el.offsetWidth); // Transform wird ignoriert
console.log(el.getBoundingClientRect().width); // Transform wird berücksichtigt
Layout-Thrashing vermeiden: erst lesen, dann schreiben
const items = [...document.querySelectorAll('.card')];
// Schlecht: Lesen und Schreiben im Wechsel erzwingt pro Durchlauf einen Reflow
// items.forEach((el) => { el.style.height = `${el.offsetWidth / 2}px`; });
// Besser: alle Werte gesammelt lesen, danach gesammelt schreiben
const widths = items.map((el) => el.offsetWidth);
requestAnimationFrame(() => {
items.forEach((el, i) => {
el.style.height = `${widths[i] / 2}px`;
});
});
// Wichtig · Fallstricke
- Rundung: Der Wert ist immer eine Ganzzahl. Für Bruchteile von Pixeln verwende
getBoundingClientRect().width. - Reflow: Das Lesen erzwingt eine synchrone Layout-Berechnung. Wiederholte Lese- und Schreibzugriffe im Wechsel führen zu Layout-Thrashing. Für laufende Größenänderungen ist
ResizeObservermeist die bessere Wahl. - Transformationen (
transform,scale) haben keinen Einfluss auf den Wert. - Bei
display: none, bei nicht eingehängten Elementen und bei Elementen mitdisplay: contentsist der Wert0. - Bei Inline-Elementen, die über mehrere Zeilen umbrechen, ist das Ergebnis nicht immer aussagekräftig. Nimm dafür
getClientRects(). - Die Eigenschaft ist schreibgeschützt: Zuweisungen werden ohne Fehlermeldung ignoriert. Die Breite änderst du über
style.width. - Es gibt sie nur bei
HTMLElement. SVG-Elemente haben keinoffsetWidth, dort hilftgetBoundingClientRect()bzw.getBBox(). - Kompatibilität: wird von allen Browsern unterstützt, seit dem CSSOM View Module standardisiert.