Safe areas & the notch: stop content hiding on iPhone and Android
How to keep buttons and text out from under the notch, Dynamic Island, punch-hole camera and home indicator — with fixes for websites/PWAs, Flutter, React Native and native Android.
Modern phones aren't rectangles. A notch or Dynamic Island cuts into the top, a punch-hole camera sits in a corner or centre, the corners are rounded, and a gesture bar runs along the bottom. Anything you place in those areas can be hidden or impossible to tap. The fix is to respect the safe area.
Where the unsafe areas are
| Device type | Top | Bottom |
|---|---|---|
| iPhone with Dynamic Island (14 Pro and newer) | ≈ 59pt (status bar + island) | 34pt home indicator |
| iPhone with notch (X – 14) | ≈ 44–50pt | 34pt |
| iPhone SE (home button) | 20pt status bar | 0 |
| Android with punch-hole | ≈ 24–48dp status bar | gesture bar, ≈ 16–48dp |
The exact values vary by device and orientation, which is why you should never hard-code them. In landscape, the notch moves to the side, so left and right insets matter too.
See it on your own app: drop a screenshot into the App checker with 🟥 Safe areas on, and the red bands show exactly what's at risk on each device.
Websites and PWAs
By default, iOS keeps web pages inside the safe area, so nothing is hidden — but you get bars of background colour around the content. If you want edge-to-edge (most PWAs do), opt in and pad:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">.app-header {
padding-top: max(12px, env(safe-area-inset-top));
}
.bottom-nav {
position: fixed; inset-inline: 0; bottom: 0;
padding-bottom: max(8px, env(safe-area-inset-bottom));
}
.page {
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}max() keeps a normal minimum padding on devices without a notch, where the inset is 0.
Flutter
// Whole screen
Scaffold(
body: SafeArea(child: MyScreen()),
);
// Only protect the bottom (e.g. a custom bottom bar)
SafeArea(top: false, child: MyBottomBar());
// Or pad one widget yourself
final insets = MediaQuery.paddingOf(context);
Padding(padding: EdgeInsets.only(top: insets.top + 8), child: header);AppBar and BottomNavigationBar already handle insets — wrapping them in another SafeArea adds double padding.
React Native / Expo
npx expo install react-native-safe-area-contextimport { SafeAreaProvider, SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }} edges={['top', 'bottom']}>
<Home />
</SafeAreaView>
</SafeAreaProvider>
);
}
// Fine-grained control
const insets = useSafeAreaInsets();
<View style={{ paddingBottom: insets.bottom + 12 }} />Prefer react-native-safe-area-context over React Native's built-in SafeAreaView, which only works on iOS.
Native Android (edge-to-edge)
Apps targeting Android 15 (API 35) are shown edge-to-edge by default, so content now draws behind the status and navigation bars. Apply the system bar insets as padding:
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
val bars = insets.getInsets(
WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()
)
v.updatePadding(left = bars.left, top = bars.top, right = bars.right, bottom = bars.bottom)
insets
}// Jetpack Compose
Scaffold { innerPadding ->
Content(Modifier.padding(innerPadding))
}
// or: Modifier.windowInsetsPadding(WindowInsets.safeDrawing)Checklist
- No button, link or icon sits in the top ~60px or bottom ~34px without inset padding.
- Backgrounds extend edge-to-edge; only content is inset.
- Fixed bottom bars add
safe-area-inset-bottom— and still look right on devices where it's 0. - Landscape is checked: the notch moves to the left or right.
- The keyboard doesn't cover inputs (see the keyboard fix in Issues & Fixes).
FAQ
What is the safe area on iPhone?
The part of the screen not covered by the status bar, notch or Dynamic Island, rounded corners and the home indicator. Content inside it is always fully visible and tappable.
How do I add safe area padding in CSS?
Add viewport-fit=cover to the viewport meta tag, then use padding with env(safe-area-inset-top), env(safe-area-inset-bottom) and the left/right insets.
How do I handle the notch in Flutter?
Wrap your screen content in a SafeArea widget, or read MediaQuery.paddingOf(context) to pad specific widgets.
Free, no signup — preview any URL on phones, tablets and desktops side by side.