Das `100vh`-Problem auf Mobilgeräten und moderne CSS-Lösungen (`dvh`, `svh`, `lvh`)
December 21, 2018
Das Erstellen eines Elements, das sich über die exakte Höhe des sichtbaren Bildschirms erstrecken soll (oft als "Above-the-Fold"- oder "Full-Screen"-Layout bezeichnet), ist eine häufige Anforderung. Der intuitive Ansatz, dafür height: 100vh (100% der Viewport-Höhe) zu verwenden, führt auf mobilen Geräten jedoch zu erheblichen Layout-Problemen.
Diese Anleitung beschreibt das Problem, stellt die modernen, nativen CSS-Lösungen vor, die das Problem vollständig lösen, und dokumentiert den historischen JavaScript-Workaround als Fallback für ältere Browser.
1. Das Problem mit 100vh auf Mobilgeräten
In mobilen Browsern (wie Safari auf iOS oder Chrome auf Android) ist die Adressleiste (URL-Bar) dynamisch. Sie wird beim Scrollen nach unten ausgeblendet und beim Scrollen nach oben wieder eingeblendet.
- Die Spezifikation: Der CSS-Standard definiert
100vhbasierend auf der Annahme, dass die Adressleiste ausgeblendet ist (bzw. berücksichtigt sie gar nicht). - Der Effekt: Wenn die Adressleiste eingeblendet ist (was beim ersten Laden der Seite immer der Fall ist), ist der tatsächliche sichtbare Bereich kleiner als
100vh. Ein Element mitheight: 100vherstreckt sich somit hinter die Adressleiste und wird unten abgeschnitten. Wichtige Elemente wie Buttons im Footer sind dadurch nicht sichtbar, ohne dass der Benutzer scrollt. - Das Verhalten der Browser: Browser-Hersteller haben sich bewusst dagegen entschieden, den
vh-Wert dynamisch beim Ein-/Ausblenden der Adressleiste anzupassen, da dies bei jedem Scrollvorgang zu einem "Ruckeln" (Reflows und Relayouts) der Seite führen würde.
2. Die moderne Lösung: Neue CSS-Viewport-Einheiten
Das CSS Values and Units Module Level 4 löst dieses Problem nativ durch die Einführung neuer, spezialisierter Viewport-Einheiten. Diese werden von allen modernen Browsern (seit ca. 2022/2023) vollständig unterstützt.
Die neuen Einheiten im Detail
svh(Small Viewport Height): Entspricht der Viewport-Höhe, wenn die dynamischen Browser-Leisten (Adressleiste, Navigation) eingeblendet (geöffnet) sind. Dies ist die sicherste Option, um sicherzustellen, dass keine Inhalte abgeschnitten werden.lvh(Large Viewport Height): Entspricht der Viewport-Höhe, wenn die dynamischen Browser-Leisten ausgeblendet (geschlossen) sind. Dies verhält sich im Wesentlichen wie das traditionellevh.dvh(Dynamic Viewport Height): Passt sich dynamisch an, wenn die Browser-Leisten ein- oder ausgeblendet werden. Während des Scrollens zoomt oder ruckelt das Layout nicht mehr unkontrolliert, da der Wert optimiert berechnet wird.
Die optimale Implementierung (mit Fallback)
Verwenden Sie 100vh als Fallback für ältere Browser und überschreiben Sie es mit 100dvh oder 100svh für moderne Browser.
.hero-section {
/* Fallback für ältere Browser */
height: 100vh;
/* Moderne, native Lösung: passt sich perfekt an die Adressleiste an */
height: 100dvh;
}
3. Der historische Workaround mit JavaScript
Bevor dvh existierte, mussten Entwickler auf JavaScript zurückgreifen, um die tatsächliche innere Fensterhöhe (window.innerHeight) zu berechnen und als CSS-Variable zur Verfügung zu stellen.
Das JavaScript-Skript
// Berechnet 1% der tatsächlichen inneren Fensterhöhe
let vh = window.innerHeight * 0.01;
// Setzt den Wert als benutzerdefinierte CSS-Variable (--vh) auf dem root-Element
document.documentElement.style.setProperty("--vh", `${vh}px`);
// Optional: Aktualisiert den Wert bei einer Größenänderung des Fensters (Resize-Event)
window.addEventListener("resize", () => {
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty("--vh", `${vh}px`);
});
Die Verwendung im CSS
.hero-section {
height: 100vh; /* Fallback */
/* Verwendet die berechnete Variable.
Fällt auf 1vh zurück, falls die Variable nicht existiert (z.B. ohne JS) */
height: calc(var(--vh, 1vh) * 100);
}
Fazit
Dank der neuen CSS-Viewport-Einheiten dvh und svh gehört das 100vh-Problem auf Mobilgeräten der Vergangenheit an. Sie bieten eine rein deklarative, performante Lösung ohne jeglichen JavaScript-Overhead. Verwenden Sie 100dvh für dynamisch mitskalierende Bereiche und 100svh, wenn Sie garantieren möchten, dass der Inhalt auch bei eingeblendeter Adressleiste vollständig sichtbar ist.