Flexbox layout and responsive design
The flexbox defaults that differ from CSS, sizing with flex and percentages, safe areas and notches, orientation changes, tablets and dark mode.
Flexbox defaults that surprise web developers
import { View, Text, StyleSheet } from 'react-native';
export function Row() {
return (
<View style={styles.container}>
<View style={styles.avatar} />
<View style={styles.body}>
<Text numberOfLines={1} style={styles.title}>A long headline that should truncate</Text>
<Text style={styles.subtitle}>Secondary line</Text>
</View>
<View style={styles.badge} />
</View>
);
}
const styles = StyleSheet.create({
container: { flexDirection: 'row', alignItems: 'center', padding: 12, gap: 12 },
avatar: { width: 44, height: 44, borderRadius: 22, backgroundColor: '#c7d2fe' },
body: { flex: 1, minWidth: 0 }, // minWidth 0 lets the text shrink and truncate
title: { fontSize: 16, fontWeight: '600' },
subtitle: { color: '#6b7280' },
badge: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 8, backgroundColor: '#e5e7eb' },
});flexDirectiondefaults tocolumn, the opposite of the CSS default.flexShrinkdefaults to 1 in React Native, andflex: 1means grow, shrink and basis zero.- A
Textinside a row needsminWidth: 0or its parent to shrink before it will truncate. - There is no cascade and no inheritance except from
Textto nestedText. Every style is explicit.
Dimensions, safe areas and tablets
import { useWindowDimensions } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export function useLayout() {
const { width, height, fontScale } = useWindowDimensions();
const insets = useSafeAreaInsets();
const isTablet = Math.min(width, height) >= 600;
const isLandscape = width > height;
const columns = width >= 900 ? 3 : width >= 600 ? 2 : 1;
const gutter = isTablet ? 24 : 16;
return { width, height, fontScale, insets, isTablet, isLandscape, columns, gutter };
}
export function Screen({ children }: { children: React.ReactNode }) {
const { insets, gutter } = useLayout();
return (
<View style={{ flex: 1, paddingTop: insets.top, paddingHorizontal: gutter }}>
{children}
</View>
);
}| Concern | API | Note |
|---|---|---|
| Notch and home indicator | useSafeAreaInsets | Wrap the app in SafeAreaProvider once |
| Orientation change | useWindowDimensions | Re-renders on change; Dimensions.get does not |
| Tablet split | Width breakpoints | Do not branch on Platform.isPad alone |
| Text scale | allowFontScaling | Leave it on; test at 200 percent |
Read dimensions from the hook rather than the static Dimensions module. The hook subscribes to changes, so a rotation updates the layout without any manual listener.
Dark mode and platform differences
import { useColorScheme, Platform, StyleSheet, Text, View } from 'react-native';
export function Card({ title }: { title: string }) {
const scheme = useColorScheme();
const isDark = scheme === 'dark';
return (
<View style={[styles.card, { backgroundColor: isDark ? '#1f2937' : '#ffffff' }]}>
<Text style={{ color: isDark ? '#f9fafb' : '#111827' }}>{title}</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
borderRadius: 12,
padding: 16,
...Platform.select({
ios: { shadowColor: '#000', shadowOpacity: 0.12, shadowRadius: 8, shadowOffset: { width: 0, height: 2 } },
android: { elevation: 2 },
default: {},
}),
},
});💡
Android
elevation and iOS shadow properties are not interchangeable. Shadow on iOS is painted by the layer; on Android it is a real elevation that also affects z-order, and it is ignored entirely on a view with a transparent background.FAQ
How do I make a layout work on a phone and a tablet?
Use width breakpoints from
useWindowDimensions and express the layout as a number of columns or a pane split. Avoid separate components per device — one adaptive layout is far less code to maintain.Why is my text truncated at a strange point?
The parent cannot shrink below its intrinsic width. Add
minWidth: 0 to the flex parent, or flexShrink: 1 to the text container, then set numberOfLines and ellipsizeMode.Related
Lists, forms and input handling Modern JavaScript and TypeScript for React Native
Last refreshed 2026-09-18.