0Pricing
React Native Academy · Aula

flex, flexGrow e dimensionamento responsivo

Use a propriedade flex para distribuir proporcionalmente o espaço disponível entre Views irmãs e crie um layout que se ajuste a qualquer largura de tela.

flex, flexGrow e dimensionamento responsivo é uma aula grátis de React Native Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Native Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Native Academy inclui 4 aulas no total.

Partes desta aula ainda não foram traduzidas e aparecem em inglês.

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.

Perguntas Frequentes

A aula “flex, flexGrow e dimensionamento responsivo” é grátis?

Sim — o texto completo de “flex, flexGrow e dimensionamento responsivo” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Native Academy, atualize para CoddyKit PRO. O curso de React Native Academy inclui 4 aulas no total.

O que vou aprender em “flex, flexGrow e dimensionamento responsivo”?

Use a propriedade flex para distribuir proporcionalmente o espaço disponível entre Views irmãs e crie um layout que se ajuste a qualquer largura de tela. Você pratica React Native Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar React Native Academy?

Nenhuma experiência prévia é necessária. React Native Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “flex, flexGrow e dimensionamento responsivo”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de React Native Academy?

Sim. Cada aula de React Native Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. StyleSheet.create e estilos embutidos
  2. Direção do Flexbox, JustifyContent e AlignItems
  3. flex, flexGrow e dimensionamento responsivo
  4. Criando uma grade de cartões responsiva
← Voltar para React Native Academy