MWCodebymw.de ↗
HTML & CSS

Notch und Home-Indikator umschiffen – env(safe-area-inset-*) in CSS

Dein Button klebt am unteren Rand und liegt auf dem iPhone genau unter dem Home-Indikator? Das löst CSS von sich aus – mit env(safe-area-inset-*) und einem Meta-Tag, das fast immer vergessen wird. Ich zeige das Muster, den häufigsten Fehler und wie du den Wert sogar im Canvas nutzt.

Es gibt einen Fehler, den ich in fast jeder mobilen Web-App sehe: Ein Element klebt per position: fixed am unteren Rand – und auf dem iPhone liegt es dann zur Hälfte hinter dem Home-Indikator. Oben dasselbe Spiel mit Notch und Dynamic Island. Dafür brauchst du keine Geräteabfrage, das Betriebssystem sagt dir die Maße selbst.

Zwei Dinge, sonst passiert nichts

Erstens braucht dein Viewport viewport-fit=cover. Ohne das legt der Browser die Seite gar nicht erst unter die Notch – die Insets sind dann alle 0, und du wunderst dich, warum dein CSS nichts tut:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">

Zweitens liest du die Werte mit env() aus. Immer mit Fallback, denn auf dem Desktop existieren sie nicht:

.bottom-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  /* 12px eigener Abstand PLUS das, was das Gerät beansprucht */
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  padding-left:   calc(env(safe-area-inset-left, 0px) + 16px);
  padding-right:  calc(env(safe-area-inset-right, 0px) + 16px);
}

.top-bar {
  position: fixed;
  top: 0;
  padding-top: calc(env(safe-area-inset-top, 0px) + 10px);
}

Die vier Werte heißen safe-area-inset-top, -right, -bottom und -left. Im Hochformat ist meist nur oben und unten etwas gesetzt, im Querformat wandert der Notch an die Seite – deshalb gehören links und rechts genauso dazu. Genau das wird am häufigsten vergessen.

Der häufigste Fehler: Padding statt Margin – und umgekehrt

Faustregel, die mir viel Ärger erspart hat:

  • Hat das Element einen Hintergrund, der bis zum Rand gehen soll (Leiste, Sheet, Banner) → padding. Die Farbe läuft dann sauber unter den Indikator, nur der Inhalt rückt nach oben.
  • Hat es keinen durchgehenden Hintergrund (schwebender Button, Toast) → margin oder direkt bottom: calc(env(safe-area-inset-bottom, 0px) + 12px).

Setzt du bei einer Leiste margin-bottom, entsteht ein hässlicher Streifen in der Hintergrundfarbe der Seite.

Bonus: den Wert in JavaScript oder im Canvas nutzen

env() gibt es nur in CSS – ein <canvas>, das ein HUD an den oberen Rand zeichnet, kann es nicht lesen. Der Trick: den Wert einmal in eine CSS-Variable schreiben und von dort abholen.

:root { --sat: env(safe-area-inset-top, 0px); }
const sat = parseFloat(
  getComputedStyle(document.documentElement).getPropertyValue('--sat')
) || 0;

ctx.fillText('Punkte: 42', 16, sat + 28);   // liegt jetzt unter der Notch

Wichtig: Beim Drehen des Geräts ändern sich die Werte. Cache den Wert also nicht für die Ewigkeit, sondern setz ihn im resize-Handler zurück – genau da bin ich in einem eigenen Spiel schon einmal reingelaufen.

Testen ohne iPhone

Du musst nicht raten. Überschreib die Variable kurz im DevTools-Konsolenfenster und schau dir das Ergebnis an:

document.documentElement.style.setProperty('--sat', '59px');

Für env() selbst geht das nicht – deshalb lohnt es sich, die Insets von Anfang an über eigene Variablen zu führen. Dann ist jedes Layout in zwei Sekunden prüfbar.

Das Ganze kostet fünf Minuten und ist der Unterschied zwischen „läuft auf dem Handy" und „fühlt sich nach App an". Mehr HTML- & CSS-Snippets aus meiner täglichen Arbeit findest du auf code.bymw.de – und wenn du eine App oder Website brauchst, die auf echten Geräten sauber sitzt, meld dich bei mir.

Quellen

#Safe Area#HTML & CSS#Mobile#PWA#Notch

Du brauchst mehr als ein Snippet?

Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.

Projekt anfragen →