The Problem

When you set viewport-fit=cover to create an edge-to-edge experience, the browser renders your content under the Dynamic Island, notch, and home indicator bar. Headers get hidden behind the pill; bottom nav bars slide under the home indicator.

Navigation Header
hidden by islandhidden by bar

Content overlapping Dynamic Island & home bar

Root Cause

Starting with iPhone X (2017), Apple introduced non-rectangular screen areas — the notch, then the Dynamic Island. When viewport-fit=cover is added to the viewport meta tag, the browser renders content edge-to-edge to fill the rounded corners. But the iOS hardware UI (Dynamic Island, home indicator) sits on top of your content and covers it.

iOS exposes the safe zones as CSS environment variables via env(), allowing you to pad your content away from these hardware elements.

Note: Without viewport-fit=cover, the browser adds letter-box padding and safe areas are automatically respected — but you lose the edge-to-edge look. The env() fix is only needed when you opt into cover mode.

Step 1 — Enable edge-to-edge

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

Step 2 — Pad with env() variables

layout.css
/* Apply safe area padding to UI chrome elements */
.app-header {
  padding-top: env(safe-area-inset-top);
}

.app-footer,
.bottom-nav {
  padding-bottom: env(safe-area-inset-bottom);
}

/* Left/right for landscape mode (iPhone notch rotates) */
.app-shell {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* Combine with a minimum padding using max() */
.bottom-nav {
  padding-bottom: 12px;
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}

/* Add to an existing padding using calc() */
.sticky-footer {
  padding-bottom: calc(1rem + env(safe-area-inset-bottom));
}
Use max() for minimum padding: max(20px, env(safe-area-inset-bottom)) ensures at least 20px of padding on older devices where the safe-area value is 0, while correctly applying the larger inset value on modern iPhones.

The four env() variables

reference.css
/* Available environment variables */
env(safe-area-inset-top)    /* Dynamic Island / status bar height */
env(safe-area-inset-right)  /* Right edge (landscape notch side) */
env(safe-area-inset-bottom) /* Home indicator height (~34px on iPhone) */
env(safe-area-inset-left)   /* Left edge (landscape non-notch side) */

Browser Support

BrowserMin VersionStatusNotes
Safari iOS 11+11+Supportedenv(safe-area-inset-*) fully supported
Safari iOS < 11< 11SupportedNo non-rectangular screens — safe area is 0, no issue
Chrome iOSAllSupportedSame WebKit engine, same env() support
Chrome Android69+Supportedenv() supported; Android handles notches differently
Firefox65+Supportedenv(safe-area-inset-*) supported
Samsung Internet9+SupportedSupported for Samsung devices with notches

Further Reading