flex, flexGrow, dan Ukuran Responsif
Gunakan properti flex untuk membagi ruang yang tersedia secara proporsional di antara View yang sejajar, lalu bangun tata letak yang menyesuaikan diri dengan lebar layar apa pun.
flex, flexGrow, dan Ukuran Responsif adalah pelajaran React Native Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar React Native Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus React Native Academy mencakup 4 pelajaran total.
Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.
The flex Property Explained
The flex property is a shorthand that sets how a View grows and shrinks to fill available space within its parent. In React Native, flex is similar to CSS's flex-grow — it represents the proportion of available space the component takes. Setting flex: 1 on a single child makes it fill all remaining space. When multiple siblings have flex values, the space is divided proportionally: a child with flex: 2 gets twice as much space as a sibling with flex: 1.
import { View } from 'react-native';
export default function FlexDemo() {
return (
<View style={{ flex: 1, flexDirection: 'column' }}>
{/* Takes 1/3 of height */}
<View style={{ flex: 1, backgroundColor: '#ff6b6b' }} />
{/* Takes 2/3 of height */}
<View style={{ flex: 2, backgroundColor: '#4f86f7' }} />
</View>
);
}flex: 1 on the Root Container
If your root App component or the outermost screen View doesn't have flex: 1, the component collapses to the size of its content — it does not fill the screen. This is one of the most common React Native bugs for beginners: the app appears to have no layout because the root View has zero height. Always set flex: 1 on the root-level View and any intermediate containers that should fill available space. Child Views without a fixed size or flex property will shrink to wrap their content.
import { View, Text, StyleSheet } from 'react-native';
// WRONG: root View has no flex, collapses to text height
function WrongLayout() {
return (
<View style={{ backgroundColor: '#f5f5f5' }}>
<Text>This View only wraps its content.</Text>
</View>
);
}
// CORRECT: flex: 1 fills the screen
function CorrectLayout() {
return (
<View style={{ flex: 1, backgroundColor: '#f5f5f5' }}>
<Text>This View fills the entire screen.</Text>
</View>
);
}flexGrow, flexShrink, and flexBasis
React Native's flex shorthand sets flexGrow, flexShrink, and flexBasis together. flexGrow controls how much a child grows into extra space. flexShrink controls how much it shrinks when space is tight. flexBasis sets the initial size before growing or shrinking (like CSS flex-basis). In practice, flex: 1 covers most use cases. Use flexShrink: 1 on a Text inside a row when you want it to shrink and show ellipsis instead of overflowing the row.
import { View, Text, StyleSheet } from 'react-native';
export default function FlexShrinkExample() {
return (
<View style={styles.row}>
<View style={styles.icon} />
{/* flexShrink: 1 allows text to shrink if the row is too small */}
<Text style={styles.label} numberOfLines={1}>
A very long label that could overflow without flexShrink
</Text>
<Text style={styles.badge}>NEW</Text>
</View>
);
}
const styles = StyleSheet.create({
row: { flexDirection: 'row', alignItems: 'center', padding: 12, gap: 8 },
icon: { width: 40, height: 40, borderRadius: 8, backgroundColor: '#4f86f7', flexShrink: 0 },
label: { flex: 1, flexShrink: 1, fontSize: 16, color: '#333' },
badge: { paddingHorizontal: 8, paddingVertical: 2, backgroundColor: '#ff6b6b', color: '#fff', borderRadius: 10, fontSize: 11, fontWeight: 'bold' },
});Dimensions API for Screen Size
To get the current screen width and height in JavaScript, use the Dimensions API from react-native. Dimensions.get('window') returns the visible app area (excluding system bars), while Dimensions.get('screen') returns the full physical screen. However, Dimensions is a static snapshot — it won't update if the user rotates the device. For responsive layouts that react to orientation changes, use the useWindowDimensions hook, which returns updated values on every resize.
import { View, Text, Dimensions, useWindowDimensions } from 'react-native';
// Static (doesn't update on rotation)
const { width, height } = Dimensions.get('window');
// Reactive (updates on rotation — preferred)
export default function ResponsiveScreen() {
const { width, height } = useWindowDimensions();
const isLandscape = width > height;
return (
<View style={{ flex: 1, padding: 16 }}>
<Text>Width: {Math.round(width)}</Text>
<Text>Height: {Math.round(height)}</Text>
<Text>Mode: {isLandscape ? 'Landscape' : 'Portrait'}</Text>
</View>
);
}Percentage Widths for Responsive Columns
Use percentage strings for width to create layouts that adapt to different screen sizes without hardcoding pixel values. A two-column grid uses width: '48%' on each card with a small gap. A three-column layout uses width: '32%'. The percentage is relative to the parent container's width. To ensure the math works, set the parent's width explicitly or make it flex: 1, and use flexWrap: 'wrap' on the row container so columns flow to the next line correctly.
import { View, StyleSheet } from 'react-native';
export default function TwoColumnGrid() {
return (
<View style={styles.grid}>
{[1, 2, 3, 4, 5, 6].map(n => (
<View key={n} style={styles.card} />
))}
</View>
);
}
const styles = StyleSheet.create({
grid: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 12,
padding: 16,
},
card: {
width: '47%', // ~2 per row with gap
height: 120,
backgroundColor: '#4f86f7',
borderRadius: 12,
},
});Combining flex with Fixed Dimensions
You can mix flex-based sizing with fixed width and height values in the same layout. A common pattern is a sidebar layout: a fixed-width side panel (e.g., width: 280) next to a content area with flex: 1 that fills the rest of the screen. The fixed-size panel takes exactly 280 points regardless of screen size, while the content panel grows or shrinks to use all remaining space. This also works for headers and footers: fixed height containers at top/bottom with a flex: 1 content area in between.
import { View, Text, StyleSheet } from 'react-native';
export default function MasterDetail() {
return (
<View style={styles.container}>
{/* Fixed-width sidebar */}
<View style={styles.sidebar}>
<Text style={{ color: '#fff' }}>Sidebar</Text>
</View>
{/* flex: 1 content fills remaining space */}
<View style={styles.content}>
<Text>Main content area</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, flexDirection: 'row' },
sidebar: { width: 200, backgroundColor: '#333', padding: 16 },
content: { flex: 1, backgroundColor: '#f5f5f5', padding: 16 },
});useWindowDimensions for Adaptive Layouts
The useWindowDimensions hook re-renders your component whenever the device orientation changes or a multi-window layout resizes. Use it to dynamically switch between single-column (portrait) and two-column (landscape) layouts. Calculate the number of columns based on the window width: if width is above a threshold (e.g., 600), switch to two or three columns. This approach makes your app look good on phones, large phones, tablets, and even desktops with Expo Web — without writing separate layout components.
import { View, StyleSheet, useWindowDimensions } from 'react-native';
export default function AdaptiveGrid({ items }) {
const { width } = useWindowDimensions();
const numColumns = width >= 768 ? 3 : width >= 480 ? 2 : 1;
const cardWidth = (width - 32 - (numColumns - 1) * 12) / numColumns;
return (
<View style={styles.grid}>
{items.map(item => (
<View key={item.id} style={[styles.card, { width: cardWidth }]} />
))}
</View>
);
}
const styles = StyleSheet.create({
grid: { flexDirection: 'row', flexWrap: 'wrap', gap: 12, padding: 16 },
card: { height: 120, backgroundColor: '#4f86f7', borderRadius: 10 },
});minWidth, maxWidth, minHeight, maxHeight
Use minWidth, maxWidth, minHeight, and maxHeight to constrain how much a View can grow or shrink. These are useful for creating components that look good across a range of content sizes without breaking at extremes. For example, a button might have a minWidth: 120 so it is always touchable even for a single-character label, but a maxWidth: 320 so it never stretches across a full tablet screen. Combining these with flex: 1 and width: '100%' is the typical pattern for centered, bounded content on larger screens.
import { View, Text, StyleSheet } from 'react-native';
export default function BoundedContent() {
return (
<View style={styles.screen}>
{/* Content is at most 480px wide, centered */}
<View style={styles.content}>
<Text style={styles.text}>This content is bounded to look good on all screen sizes.</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, alignItems: 'center', backgroundColor: '#f5f5f5', padding: 16 },
content: {
width: '100%',
maxWidth: 480, // doesn't stretch on tablets/web
backgroundColor: '#fff',
borderRadius: 12,
padding: 20,
},
text: { fontSize: 16, lineHeight: 24, color: '#333' },
});Aspect Ratio for Consistent Proportions
The aspectRatio style property sets the width-to-height ratio of a component. When the width is set (or determined by flex), aspectRatio automatically computes the height to maintain the proportion. aspectRatio: 16/9 creates a widescreen video thumbnail. aspectRatio: 1 creates a perfect square. This is especially powerful for media content that must adapt to different screen widths — the height automatically scales proportionally without any calculations or JavaScript.
import { View, Image, StyleSheet } from 'react-native';
export default function VideoThumbnail() {
return (
<View style={styles.thumbnailContainer}>
<Image
source={{ uri: 'https://picsum.photos/640/360' }}
style={styles.thumbnail}
/>
</View>
);
}
const styles = StyleSheet.create({
thumbnailContainer: {
width: '100%',
},
thumbnail: {
width: '100%',
aspectRatio: 16 / 9, // height auto-computed = width * 9/16
borderRadius: 10,
},
});Three-Panel Responsive Layout
Bring together all the sizing concepts: flex, maxWidth, and useWindowDimensions to build a classic three-panel layout for a note-taking or email app. On small phones, only one panel shows at a time. On tablets in landscape, all three panels appear side by side using flex ratios. This adaptive pattern is achievable with React Native's Flexbox and dimension hooks — no complex CSS media queries or separate layouts needed.
import { View, useWindowDimensions, StyleSheet } from 'react-native';
export default function ThreePanel() {
const { width } = useWindowDimensions();
const isTablet = width >= 768;
if (!isTablet) {
// Phone: single panel
return <View style={{ flex: 1, backgroundColor: '#f5f5f5' }} />;
}
// Tablet: three panels
return (
<View style={styles.row}>
<View style={[styles.panel, { flex: 1 }]} />
<View style={[styles.panel, { flex: 2, backgroundColor: '#e8f0fe' }]} />
<View style={[styles.panel, { flex: 2 }]} />
</View>
);
}
const styles = StyleSheet.create({
row: { flex: 1, flexDirection: 'row' },
panel: { backgroundColor: '#f5f5f5', borderRightWidth: 1, borderRightColor: '#ddd' },
});Avoiding Layout Pitfalls
Common React Native layout pitfalls to watch for: missing flex: 1 on a container makes it collapse to zero height; percentage widths without a sized parent resolve to zero; fixed heights in deeply nested views cause clipping on small screens; minHeight instead of flex on scroll containers prevents proper sizing. Debug by temporarily adding backgroundColor tints to each View — you'll immediately see which boxes are sized correctly and which are collapsing. When a component is invisible, suspect a zero-height parent before looking at the component's own styles.
// Debugging checklist when a component is invisible:
// 1. Does its parent have flex: 1 or an explicit height?
// 2. Does the component itself have flex or height/width?
// 3. Are percentage dimensions resolving against a zero-width parent?
// 4. Is backgroundColor set (to verify the View is rendered but transparent)?
// Quick visibility check:
<View style={{ flex: 1, backgroundColor: 'rgba(255,0,0,0.1)' }}>
{/* If this shows red tint, the container is sized correctly */}
<YourComponent />
</View>Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: flex: 1 fills remaining available space proportionally, useWindowDimensions provides reactive screen dimensions for orientation-aware layouts, and aspectRatio automatically computes height from width to maintain consistent proportions. Next up we explore building a responsive card grid with Flexbox wrapping.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “flex, flexGrow, dan Ukuran Responsif” gratis?
Ya — teks lengkap “flex, flexGrow, dan Ukuran Responsif” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus React Native Academy, upgrade ke CoddyKit PRO. Kursus React Native Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “flex, flexGrow, dan Ukuran Responsif”?
Gunakan properti flex untuk membagi ruang yang tersedia secara proporsional di antara View yang sejajar, lalu bangun tata letak yang menyesuaikan diri dengan lebar layar apa pun. Kamu berlatih React Native Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai React Native Academy?
Tidak diperlukan pengalaman sebelumnya. React Native Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “flex, flexGrow, dan Ukuran Responsif” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran React Native Academy ini?
Ya. Setiap pelajaran React Native Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- StyleSheet.create dan Gaya Sebaris
- Arah Flexbox, JustifyContent, dan AlignItems
- flex, flexGrow, dan Ukuran Responsif
- Membangun Kisi Kartu Responsif