Signatur
Beschreibung
Die schreibgeschützte Eigenschaft window.innerWidth gibt die Breite des Layout-Viewports in CSS-Pixeln als ganze Zahl zurück. Dazu zählt der Inhaltsbereich des Fensters und die Breite einer vertikalen Scrollleiste, falls eine angezeigt wird. Fensterrahmen, Seitenleisten und Werkzeugleisten des Browsers zählen nicht dazu.
Typische Einsatzfälle sind responsive Logik in JavaScript, z. B. das Umschalten zwischen mobiler und Desktop-Navigation, das Berechnen von Canvas-Größen oder das Positionieren von Popovers und Tooltips. Weil innerWidth die Scrollleiste mitzählt, entspricht der Wert genau der Breite, die CSS-Media-Queries wie @media (min-width: 768px) auswerten.
Brauchst du die tatsächlich nutzbare Breite ohne Scrollleiste, verwende document.documentElement.clientWidth. Die Außenbreite des gesamten Browserfensters samt Rahmen liefert window.outerWidth. Für die sichtbare Fläche beim Pinch-Zoom auf Mobilgeräten ist window.visualViewport.width die richtige Wahl.
In einem <iframe> bezieht sich innerWidth auf das Fenster des Frames, nicht auf das umgebende Dokument. Um bei Größenänderungen zu reagieren, lauscht man auf das resize-Ereignis oder nutzt – oft besser – matchMedia() bzw. ResizeObserver.
Rückgabewert
Beispiele
Viewport-Breite mit und ohne Scrollleiste vergleichen
const mitScrollleiste = window.innerWidth;
const ohneScrollleiste = document.documentElement.clientWidth;
const scrollleistenBreite = mitScrollleiste - ohneScrollleiste;
console.log(`Viewport: ${mitScrollleiste}px`);
console.log(`Nutzbar: ${ohneScrollleiste}px`);
console.log(`Scrollleiste: ${scrollleistenBreite}px`);
Layout bei Größenänderung umschalten (gedrosselt)
const BREAKPOINT = 768;
let frameId = null;
const aktualisiereLayout = () => {
const istMobil = window.innerWidth < BREAKPOINT;
document.body.classList.toggle('mobil', istMobil);
console.log(`Breite ${window.innerWidth}px → ${istMobil ? 'mobil' : 'desktop'}`);
};
const onResize = () => {
if (frameId) return;
frameId = requestAnimationFrame(() => {
frameId = null;
aktualisiereLayout();
});
};
window.addEventListener('resize', onResize);
aktualisiereLayout();
// Später aufräumen, z. B. beim Unmount einer Komponente:
// window.removeEventListener('resize', onResize);
Canvas scharf auf Viewport-Breite skalieren
const canvas = document.createElement('canvas');
document.body.append(canvas);
const passeCanvasAn = () => {
const dpr = window.devicePixelRatio || 1;
const breite = document.documentElement.clientWidth;
const hoehe = window.innerHeight;
canvas.style.width = `${breite}px`;
canvas.style.height = `${hoehe}px`;
canvas.width = Math.round(breite * dpr);
canvas.height = Math.round(hoehe * dpr);
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);
ctx.fillText(`innerWidth: ${window.innerWidth}`, 10, 20);
};
window.addEventListener('resize', passeCanvasAn);
passeCanvasAn();
Besser für Breakpoints: matchMedia statt resize-Polling
const mq = window.matchMedia('(min-width: 768px)');
const handle = (e) => {
console.log(e.matches ? 'Desktop-Layout' : 'Mobil-Layout', window.innerWidth);
};
mq.addEventListener('change', handle);
handle(mq);
// Wichtig · Fallstricke
- Scrollleiste inklusive:
innerWidthenthält die vertikale Scrollleiste. Wer z. B. Elemente exakt bündig platzieren will, erhält mitdocument.documentElement.clientWidthdie korrekte, nutzbare Breite. Auf Mobilgeräten und bei Overlay-Scrollleisten (macOS) sind beide Werte meist gleich. - Zoom: Beim Browser-Zoom (Strg +/−) ändert sich
innerWidth, weil sich die Anzahl der CSS-Pixel ändert. Beim Pinch-Zoom auf Mobilgeräten bleibt der Wert dagegen gleich – dafür gibt eswindow.visualViewport.width. - Meta-Viewport: Fehlt
<meta name="viewport" content="width=device-width">, melden mobile Browser oft eine virtuelle Breite von ca. 980px. - Performance: Das Lesen kann einen synchronen Layout-Reflow auslösen. In
resize-Handlern daher drosseln (requestAnimationFrame, Debounce) und Lese- und Schreibzugriffe auf das DOM nicht abwechselnd mischen. - Schreibgeschützt: Eine Zuweisung ändert die Fenstergröße nicht; dafür gibt es
window.resizeTo(), das aber nur bei per Skript geöffneten Popups funktioniert. - Kompatibilität: Wird von allen modernen Browsern unterstützt (IE ab Version 9). In Node.js existiert
windownicht – bei SSR vorhertypeof window !== 'undefined'prüfen.