Without it in your viewport meta tag, every env(safe-area-inset-*) resolves to 0 and nothing you write has any effect.
<!-- 1. Opt in, or the env() values stay 0 -->
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
/* 2. Inset anything that touches a screen edge */
.app-bar {
padding-top: env(safe-area-inset-top);
}
/* 3. max() gives you a floor on devices with no inset */
.bottom-nav {
padding-bottom: max(1rem, env(safe-area-inset-bottom));
}
/* 4. Landscape puts the notch on the side */
.content {
padding-left: max(1rem, env(safe-area-inset-left));
padding-right: max(1rem, env(safe-area-inset-right));
}
Safe area insets by device
| Top | Bottom | Screen type | Devices | Models |
|---|---|---|---|---|
| 62 px | 34 px | Dynamic Island, iPhone Air | 6 | iPhone Air, iPhone 17 Pro Max, iPhone 17 Pro, iPhone 17, iPhone 16 Pro Max, iPhone 16 Pro |
| 59 px | 34 px | Dynamic Island | 8 | iPhone 16 Plus, iPhone 16, iPhone 15 Pro Max, iPhone 15 Pro, iPhone 15 Plus, iPhone 15 +2 more |
| 48 px | 34 px | Notch | 4 | iPhone 11 Pro Max, iPhone 11, iPhone XR, iPhone XS Max |
| 47 px | 34 px | Notch | 10 | iPhone 17e, iPhone 16e, iPhone 14 Plus, iPhone 14, iPhone 13 Pro Max, iPhone 13 Pro +4 more |
| 44 px | 34 px | Notch | 5 | iPhone 13 mini, iPhone 12 mini, iPhone 11 Pro, iPhone XS, iPhone X |
| 24 px | 20 px | iPad Pro 13″, home indicator | 24 | iPad Pro 13″ (M5), iPad Pro 11″ (M5), iPad Air 13″ (M4), iPad Air 11″ (M4), iPad Pro 13″ (M4), iPad Pro 11″ (M4) +18 more |
| 20 px | 0 px | Home button, status bar only | 16 | iPhone SE (3rd gen), iPhone SE (2nd gen), iPhone SE (1st gen), iPhone 8 Plus, iPhone 8, iPhone 7 Plus +10 more |
Questions
What is a safe area inset?
The margin between the edge of the screen and the area your content can safely occupy. It exists because of notches, the Dynamic Island, rounded corners and the home indicator. CSS exposes it through env(safe-area-inset-top) and its three siblings.
How do I use safe area insets in CSS?
Two steps. Add viewport-fit=cover to your viewport meta tag — without it the insets are always zero. Then apply env(safe-area-inset-*) as padding on whatever touches the screen edge.
Why are my env() values always 0?
Almost always the missing viewport-fit=cover. On desktop browsers and Android devices without cutouts they are legitimately 0 — which is why max() is useful: padding-bottom: max(1rem, env(safe-area-inset-bottom)) gives you a sensible floor.
What is the safe area on an iPhone?
It varies by generation. Devices with a notch use a 44–48 px top inset; Dynamic Island models use 59–62 px. The bottom home indicator is a consistent 34 px across all of them. The table below lists every model.
env() output. Always read them at runtime rather than hard-coding — this table is for planning, not production.