This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Safe areas

Edit page

Learn how to add safe areas for screen components inside your Expo project.


Creating a safe area ensures your app screen's content is positioned correctly. This means it doesn't get overlapped by notches, status bars, home indicators, and other interface elements that are part of the device's physical hardware or are controlled by the operating system. When the content gets overlapped, it gets concealed by these interface elements.

Here's an example of an app screen's content getting concealed by the status bar on Android. On iOS, the same content is concealed by rounded corners, notch, and the status bar.

Use react-native-safe-area-context library

react-native-safe-area-context provides a flexible API for handling Android and iOS device's safe area insets. It also provides a SafeAreaView component that you can use instead of a <View> to account for safe areas automatically in your screen components.

Using the library, the result of the previous example changes as it displays the content inside a safe area, as shown below:

Installation

You can skip installing react-native-safe-area-context if you have created a project using the default template. This library is installed as peer dependency for Expo Router library. Otherwise, install it by running the following command:

Terminal
- npx expo install react-native-safe-area-context
- yarn expo install react-native-safe-area-context
- pnpm expo install react-native-safe-area-context
- bun expo install react-native-safe-area-context

Usage

You can directly use SafeAreaView to wrap the content of your screen's component. It is a regular <View> with the safe area insets applied as extra padding or margin.

src/app/index.tsx
import { Text } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; export default function HomeScreen() { return ( <SafeAreaView style={{ flex: 1 }}> <Text>Content is in safe area.</Text> </SafeAreaView> ); }
Using a different Expo template and don't have Expo Router installed?

Import and add SafeAreaProvider to the root component file (such as App.tsx) before using SafeAreaView in your screen component.

App.tsx
import { SafeAreaProvider } from 'react-native-safe-area-context'; export default function App() { return ( <SafeAreaProvider> {/* Your app content */} </SafeAreaProvider> ); }

Alternate: useSafeAreaInsets hook

Alternate to SafeAreaView, you can use useSafeAreaInsets hook in your screen component. It provides direct access to the safe area insets, allowing you to apply padding for each edge of the <View> using an inset from this hook.

The example below uses the useSafeAreaInsets hook. It applies top padding to a <View> using insets.top.

src/app/index.tsx
import { Text, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; export default function HomeScreen() { const insets = useSafeAreaInsets(); return ( <View style={{ flex: 1, paddingTop: insets.top }}> <Text>Content is in safe area.</Text> </View> ); }

The hook provides the insets in the following object:

{ top: number, right: number, bottom: number, left: number }

Additional information

Minimal example

Below is a minimal working example that uses the useSafeAreaInsets hook to apply top padding to a view.

Using react-native-safe-area-context
import { Text, View } from 'react-native'; import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; function HomeScreen() { const insets = useSafeAreaInsets(); return ( <View style={{ flex: 1, paddingTop: insets.top }}> <Text style={{ fontSize: 28 }}>Content is in safe area.</Text> </View> ); } export default function App() { return ( <SafeAreaProvider> <HomeScreen /> </SafeAreaProvider> ); }

Usage with React Navigation

By default, React Navigation supports safe areas and uses react-native-safe-area-context as a peer dependency. For more information, see the React Navigation documentation.

Usage with web

On web, use CSS env(safe-area-inset-*) values for safe-area spacing. The browser applies these values across client rendering, server rendering, and static generation. CSS safe-area spacing does not require the react-native-safe-area-context library.

With Expo Router, create src/safe-area.css and import it in your existing root layout:

src/app/_layout.tsx
import '../safe-area.css';

Apply a class to an element in a web-specific route:

src/app/index.web.tsx
export default function HomeScreen() { return <main className="safe-area-content">Content is in the safe area.</main>; }

In src/safe-area.css, define the spacing for the safe-area-content class:

src/safe-area.css
.safe-area-content { padding-top: env(safe-area-inset-top, 0px); padding-right: env(safe-area-inset-right, 0px); padding-bottom: env(safe-area-inset-bottom, 0px); padding-left: env(safe-area-inset-left, 0px); }

The browser provides the safe-area-inset-* environment variables. These values specify the distance from their respective edge of the viewport to the safe area, keeping content clear of notches and rounded corners. The env() function is used to read these values. See the CSS env() reference for details.

The browser updates this spacing without a React state update. Keep a corresponding src/app/index.tsx route using react-native-safe-area-context for Android and iOS.

Static and server exports include the stylesheet in the initial HTML.

In development, async routes can load layout CSS after streamed content and cause a layout shift. To avoid this development limitation, render the rules in a <style> element inside the <head> of your Root HTML component. Use src/app/+html.tsx for this component. CSS imports in +html.tsx are not supported.

In SDK 58 and later, Expo Router disables automatic safe-area measurements on web to preserve streamed content during hydration. Do not add another SafeAreaProvider to restore these measurements. Its updates can interrupt hydration and discard pending streamed content, even if you provide initialMetrics.

See the safe-area context reference for the behavior of its hooks and components. CSS values do not change the numbers returned by these hooks.

Without Expo Router, the library's provider still supports web measurements. If you use its components or hooks, configure SafeAreaProvider as described in the usage section. CSS remains the recommended approach for web spacing.