Flexbox Direction, JustifyContent, AlignItems
Control how children are arranged inside a View using flexDirection, justifyContent, and alignItems to center, space, and align elements.
Flexbox Direction, JustifyContent, AlignItems is a free React Native Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Native Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Flexbox Is the Default Layout System
React Native uses Flexbox as its layout algorithm for every View component — there is no block or inline layout like in CSS. Every View is automatically a Flex container, meaning its children are positioned according to Flexbox rules by default. The key difference from web CSS Flexbox is that React Native's default flexDirection is 'column', not 'row' like on the web. This means children stack vertically by default, which matches how most mobile screens are laid out.
import { View, StyleSheet } from 'react-native';
export default function DefaultFlex() {
return (
// No flexDirection needed — 'column' is the default
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box3} />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#f5f5f5', padding: 16 },
box1: { height: 60, backgroundColor: '#ff6b6b', marginBottom: 8 },
box2: { height: 60, backgroundColor: '#4f86f7', marginBottom: 8 },
box3: { height: 60, backgroundColor: '#51cf66' },
});flexDirection: row vs column
flexDirection sets the main axis of the Flex container. With 'column' (default), children stack top to bottom. With 'row', children sit left to right. The values 'column-reverse' and 'row-reverse' reverse the order. Changing flexDirection also changes which axis justifyContent and alignItems affect — justifyContent always works along the main axis, and alignItems along the cross axis. This is the single most impactful Flexbox property to understand.
import { View, StyleSheet } from 'react-native';
export default function DirectionDemo() {
return (
<View style={{ flex: 1, gap: 16, padding: 16 }}>
{/* Column: children stack vertically (default) */}
<View style={{ flexDirection: 'column', height: 120, backgroundColor: '#f0f0f0' }}>
<View style={styles.box} />
<View style={styles.box} />
</View>
{/* Row: children sit side by side */}
<View style={{ flexDirection: 'row', height: 60, backgroundColor: '#f0f0f0' }}>
<View style={styles.box} />
<View style={styles.box} />
</View>
</View>
);
}
const styles = StyleSheet.create({
box: { width: 50, height: 50, backgroundColor: '#4f86f7', margin: 4 },
});justifyContent: Aligning Along the Main Axis
justifyContent controls how children are distributed along the main axis (vertical for column, horizontal for row). The most useful values are: 'flex-start' (pack at start, default), 'flex-end' (pack at end), 'center' (center the group), 'space-between' (first and last touch the edges, equal gaps between others), 'space-around' (equal space around each child), and 'space-evenly' (equal space including edges). 'space-between' is particularly common for navigation bars and action button rows.
import { View, Text, StyleSheet } from 'react-native';
export default function SpaceBetween() {
return (
<View style={styles.row}>
<Text style={styles.tab}>Home</Text>
<Text style={styles.tab}>Search</Text>
<Text style={styles.tab}>Profile</Text>
</View>
);
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
justifyContent: 'space-between', // distribute across full width
paddingHorizontal: 24,
paddingVertical: 16,
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#eee',
},
tab: { fontSize: 14, color: '#666' },
});alignItems: Aligning Along the Cross Axis
alignItems controls how children are positioned on the cross axis (perpendicular to the main axis). For a column container it aligns children horizontally; for a row container it aligns them vertically. Values: 'flex-start' (default for column on Android, items hug the start), 'flex-end', 'center', and 'stretch' (items expand to fill the cross axis — this is the default on iOS and makes sense for column layouts where you want full-width children). 'baseline' aligns text baselines of children.
import { View, Text, StyleSheet } from 'react-native';
export default function AlignDemo() {
return (
<View style={styles.container}>
{/* Row: alignItems centers children vertically */}
<View style={styles.row}>
<Text style={styles.smallText}>Small</Text>
<Text style={styles.largeText}>LARGE</Text>
<Text style={styles.smallText}>Small</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 20 },
row: {
flexDirection: 'row',
alignItems: 'center', // vertically center all items
backgroundColor: '#e8f0fe',
padding: 16,
borderRadius: 8,
},
smallText: { fontSize: 12, color: '#666', marginHorizontal: 8 },
largeText: { fontSize: 28, fontWeight: 'bold', color: '#111', marginHorizontal: 8 },
});Centering Content with flex, justify, and align
A very common pattern is centering content both vertically and horizontally — for splash screens, empty states, or loading indicators. Set the container to flex: 1 so it fills available space, then apply justifyContent: 'center' and alignItems: 'center'. Since the default flexDirection is column, this centers children in the middle of the screen both vertically and horizontally. This three-property combination is probably the most-used layout recipe in React Native.
import { View, Text, StyleSheet } from 'react-native';
export default function CenteredScreen() {
return (
<View style={styles.container}>
<Text style={styles.emoji}>🎯</Text>
<Text style={styles.title}>Nothing here yet</Text>
<Text style={styles.subtitle}>Add your first item to get started</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center', // vertical center (column main axis)
alignItems: 'center', // horizontal center (column cross axis)
backgroundColor: '#f8f9fa',
},
emoji: { fontSize: 56, marginBottom: 16 },
title: { fontSize: 22, fontWeight: 'bold', color: '#333' },
subtitle: { fontSize: 14, color: '#999', marginTop: 8, textAlign: 'center' },
});alignSelf: Overriding Cross-Axis Alignment
alignSelf overrides the parent's alignItems for a specific child. It accepts the same values as alignItems: 'auto' (use parent's setting), 'flex-start', 'flex-end', 'center', and 'stretch'. This is useful when most siblings share one alignment but one child needs different treatment — for example, a row of icons where one is larger and should align to the top while the others center. Use alignSelf sparingly; it's more maintainable to adjust the parent's alignItems and use wrapper Views when needed.
import { View, Text, StyleSheet } from 'react-native';
export default function AlignSelfExample() {
return (
<View style={styles.row}>
<View style={styles.boxSmall} />
{/* This box aligns to flex-end independently */}
<View style={[styles.boxSmall, { alignSelf: 'flex-end', backgroundColor: 'red' }]} />
<View style={styles.boxSmall} />
</View>
);
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center', // default for siblings
height: 100,
backgroundColor: '#e8f0fe',
padding: 8,
gap: 8,
},
boxSmall: { width: 50, height: 50, backgroundColor: '#4f86f7', borderRadius: 6 },
});gap, rowGap, and columnGap
Instead of adding margin to each child, use gap on the container to set uniform spacing between flex children. gap sets both row and column gaps, while rowGap and columnGap control them independently. This eliminates the need for marginBottom on all but the last child, or the hack of adding negative margin to the container. Gap support was added in React Native 0.71 (available in Expo SDK 48+), so check your RN version before using it in older projects.
import { View, StyleSheet } from 'react-native';
export default function GapExample() {
return (
<View style={styles.container}>
{[1, 2, 3, 4].map(n => (
<View key={n} style={styles.card} />
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
gap: 12, // equal gap between all children
padding: 16,
backgroundColor: '#f5f5f5',
},
card: {
width: '47%', // two columns
height: 100,
backgroundColor: '#4f86f7',
borderRadius: 10,
},
});flexWrap: Wrapping Children to Next Lines
By default, flex children shrink to fit in a single line and never wrap. Set flexWrap: 'wrap' on the container to let children wrap to the next row (for row direction) or next column (for column direction) when they run out of space. This is the foundation for tag clouds, grid-like layouts with percentage widths, and any UI where items should flow onto the next line naturally. 'nowrap' is the default; 'wrap-reverse' wraps in the opposite direction.
import { View, Text, StyleSheet } from 'react-native';
const tags = ['React Native', 'Mobile', 'iOS', 'Android', 'JavaScript', 'Flexbox', 'Expo'];
export default function TagCloud() {
return (
<View style={styles.container}>
{tags.map(tag => (
<View key={tag} style={styles.tag}>
<Text style={styles.tagText}>{tag}</Text>
</View>
))}
</View>
);
}
const styles = StyleSheet.create({
container: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, padding: 16 },
tag: { backgroundColor: '#e8f0fe', paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16 },
tagText: { color: '#4f86f7', fontSize: 13, fontWeight: '500' },
});A Practical Header Layout
Apply your Flexbox knowledge to build a common mobile app pattern: a navigation header with a back button on the left, a centered title, and a menu icon on the right. Use flexDirection: 'row' and alignItems: 'center' on the header container. Give the title flex: 1 so it expands to fill the remaining space and centers itself between the fixed-width side icons. This is cleaner than using position: 'absolute' for centering and handles varying title lengths correctly.
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
export default function Header({ title, onBack, onMenu }) {
return (
<View style={styles.header}>
<TouchableOpacity style={styles.sideBtn} onPress={onBack}>
<Text style={styles.icon}>←</Text>
</TouchableOpacity>
<Text style={styles.title} numberOfLines={1}>{title}</Text>
<TouchableOpacity style={styles.sideBtn} onPress={onMenu}>
<Text style={styles.icon}>⋯</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
header: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 12,
backgroundColor: '#fff',
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#ddd',
},
sideBtn: { width: 40, alignItems: 'center' },
title: { flex: 1, fontSize: 18, fontWeight: '600', color: '#111', textAlign: 'center' },
icon: { fontSize: 22, color: '#333' },
});Debugging Flexbox Layouts
Flexbox bugs are common during layout development. Useful debugging techniques: add a temporary backgroundColor to each View to make its boundaries visible, use React DevTools to inspect the computed layout in the component tree, check whether flex: 1 is missing from ancestor containers (a container without flex: 1 collapses to zero height, making its children invisible), and verify that flexDirection is the value you intend (remember, React Native defaults to column, not row). Removing all styles and adding them back one by one is a reliable way to isolate layout bugs.
// Debug technique: color-code your Views temporarily
const debugStyles = StyleSheet.create({
container: { flex: 1, backgroundColor: 'rgba(255,0,0,0.1)' }, // red tint
inner: { backgroundColor: 'rgba(0,0,255,0.1)' }, // blue tint
text: { backgroundColor: 'rgba(0,255,0,0.1)' }, // green tint
});
// Then you can see exactly where each View starts and ends
// Remove these debug colors before shipping!Row with Icon, Text, and Action
One of the most common mobile UI patterns is a list row with an icon on the left, text in the middle, and an action button on the right. Implement it with flexDirection: 'row' on the container, alignItems: 'center' to vertically align all children, a fixed-size icon View on the left, a flex: 1 text area in the middle (so it expands to fill available space), and a fixed-size action button on the right. This pattern appears in settings screens, contact lists, and any data-dense table view in mobile apps.
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
export default function SettingsRow({ icon, label, subtitle, onPress }) {
return (
<TouchableOpacity style={styles.row} onPress={onPress}>
{/* Left: icon */}
<View style={styles.iconContainer}>
<Text style={{ fontSize: 22 }}>{icon}</Text>
</View>
{/* Middle: text content — flex: 1 fills space */}
<View style={{ flex: 1 }}>
<Text style={styles.label} numberOfLines={1}>{label}</Text>
{subtitle && <Text style={styles.subtitle} numberOfLines={1}>{subtitle}</Text>}
</View>
{/* Right: chevron */}
<Text style={styles.chevron}>›</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
row: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#fff', gap: 12 },
iconContainer: { width: 36, height: 36, borderRadius: 8, backgroundColor: '#f0f4ff', alignItems: 'center', justifyContent: 'center' },
label: { fontSize: 16, color: '#222' },
subtitle: { fontSize: 13, color: '#999', marginTop: 2 },
chevron: { fontSize: 22, color: '#ccc', fontWeight: '300' },
});Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: flexDirection sets the main axis (column by default in React Native, not row), justifyContent distributes children along the main axis, and alignItems aligns children on the cross axis. Next up we explore the flex property and responsive sizing across screen dimensions.
Frequently asked questions
Is the “Flexbox Direction, JustifyContent, AlignItems” lesson free?
Yes — the full text of “Flexbox Direction, JustifyContent, AlignItems” is free to read here on the web, and the React Native Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Native Academy course, upgrade to CoddyKit PRO.
What will I learn in “Flexbox Direction, JustifyContent, AlignItems”?
Control how children are arranged inside a View using flexDirection, justifyContent, and alignItems to center, space, and align elements. You practise React Native Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Native Academy?
No prior experience is required. React Native Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Flexbox Direction, JustifyContent, AlignItems” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Native Academy lesson?
Yes. Every React Native Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- StyleSheet.create and Inline Styles
- Flexbox Direction, JustifyContent, AlignItems
- flex, flexGrow, and Responsive Sizing
- Building a Responsive Card Grid