Safe areas and the keyboard
You'll learn to keep your screen clear of the notch, the status bar and the keyboard.
Watch & read
Start with the required ones. The others are there when you need them.
Explanation
A phone screen is not a clean rectangle. At the top there is the status bar with the clock and battery,
and often a notch or camera hole. At the bottom there may be a home bar. Apps draw behind all of these,
on iPhone and on new Android phones too. So a Text at the very top of your screen can end up under the
clock.
Think of a wall poster with a light switch on it. You don't write over the switch; you leave a margin around it. The part of the screen nothing covers is the safe area.
import { SafeAreaView } from "react-native-safe-area-context";<SafeAreaView style={{ flex: 1 }}><Text>My habits</Text></SafeAreaView>
SafeAreaView is a normal View that adds just enough padding on each edge for this exact phone. Use the
one from react-native-safe-area-context. React Native has an old SafeAreaView of its own, but it is
deprecated and only worked on iPhone. New Expo projects with Expo Router already have the package. If you
only want some edges, say which: edges={["top"]}.
You don't always need it. A screen with a Stack header already sits below the status bar, because the
header handles the top. A tab bar handles the bottom. You need it on screens with no header, like your home
screen inside tabs with headerShown: false.
The keyboard is the other thing that covers your screen. When someone taps a TextInput near the
bottom, the keyboard slides up over it. KeyboardAvoidingView moves your content up out of the way:
<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : undefined} style={{ flex: 1 }}>
Platform.OS is "ios" or "android". The Expo docs use "padding" on iPhone and nothing on Android,
where the system already moves the content for you. Try other values if your screen still gets covered.
People often check only the browser preview. A browser has no notch and no on-screen keyboard, so the problem never shows. Always open the screen in Expo Go on a real phone, and tap the input at the bottom.
When you read a screen, look at its outermost component: is it a SafeAreaView, or is there a header above
it? If it has a TextInput near the bottom, look for a KeyboardAvoidingView.
Code tour
Click a line number with a ring to read the note for that line.
Practice
Short drills. Take your time and read the code before you answer.
1export default function App() {2 return (3 <View style={{ flex: 1, backgroundColor: "#0B0B0D" }}>4 <Text style={{ color: "white", fontSize: 28 }}>My habits</Text>5 </View>6 );7}8// No header, no SafeAreaView. You open it in Expo Go9// on an iPhone with a notch at the top.
1import { StyleSheet, Text, TextInput, View } from "react-native";2import { SafeAreaProvider } from "react-native-safe-area-context";34function AddHabitScreen() {5 return (6 <View style={styles.screen}>
Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.
Quick check
3 questions. Each one explains itself after you answer.
- 1 / 3Which
SafeAreaViewshould you use in a new Expo app? - 2 / 3Your screen is inside a Stack and shows a header with a title. Does its content need a
SafeAreaViewat the top? - 3 / 3A
TextInputis at the bottom of the screen. What happens when you tap it, with noKeyboardAvoidingView?