Noções Básicas de Estilização
10 exemplos para você começar com Estilização e Layout - 7 básicos e 3 intermediários.
Busque em todas as páginas da documentação
10 exemplos para você começar com Estilização e Layout - 7 básicos e 3 intermediários.
A estilização do React Native roda em um motor de layout nativo, não em um navegador. A maneira mais rápida de experimentar estes trechos é com um projeto Expo com o template TypeScript padrão.
npx create-expo-app@latest MyApp
cd MyApp
npx expo startSubstitua App.tsx por qualquer um dos exemplos abaixo. react-native-safe-area-context vem com o Expo - envolva sua raiz com SafeAreaProvider (o template padrão já faz isso).
Ferramentas: Estes exemplos visam Expo SDK 57, React Native 0.86 e React 19.2.3. As dimensões são em pixels independentes de densidade (dp), não
remouem.
Defina objetos de estilo reutilizáveis com StyleSheet.create em vez de espalhar literais pelo JSX.
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.card}>
<Text style={styles.title}>StyleSheet.create</Text>
<Text style={styles.body}>
Chaves nomeadas mantêm os estilos organizados e validados em tempo de desenvolvimento.
</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
margin: 16,
padding: 20,
backgroundColor: "#f0f4ff",
borderRadius: 12,
},
title: { fontSize: 18, fontWeight: "600", marginBottom: 8 },
body: { fontSize: 14, lineHeight: 20, color: "#374151" },
});backgroundColor, borderRadius) - nomes CSS com hífen são inválidosStyleSheet.create valida as chaves em desenvolvimento e registra os estilos uma vez para que o lado nativo receba IDs estáveisvh/vwstyles no escopo do módulo para que não sejam recriados a cada renderizaçãoRelacionado: Desempenho de Estilização - por que estilos em cache são importantes em dispositivos móveis | Melhores Práticas de Estilização - nomenclatura e organização de arquivos
Objetos de estilo inline funcionam para casos únicos, mas uma nova referência de objeto é criada a cada renderização, a menos que você a memorize.
import { View, Text, StyleSheet } from "react-native";
const PADDING = 16;
export default function App() {
const isHighlighted = true;
return (
<View style={styles.container}>
<View style={styles.box}>
<Text>Em cache via StyleSheet</Text>
</View>
<View style={{ padding: PADDING, backgroundColor: "#fde68a" }}>
<Text>Literal inline - bom para casos únicos raros</Text>
</View>
<View
style={[
styles.box,
isHighlighted && { borderWidth: 2, borderColor: "#2563eb" },
]}
>
<Text>Base em cache + pequena sobrescrita inline</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16, gap: 12 },
box: { padding: 16, backgroundColor: "#bbf7d0", borderRadius: 8 },
});style={{ padding: 16 }} aloca um novo objeto a cada renderização - inofensivo para uma única prop estática, custoso quando passado profundamente em listasStyleSheet.create para qualquer coisa reutilizada ou composta entre componentesuseMemo são aceitáveis - profile antes de otimizarPADDING no escopo do módulo evitam números mágicos sem disparar recriaçãoRelacionado: Desempenho de Estilização -
useMemopara estilos dinâmicos e armadilhas de listas
Cada View é um contêiner flexível. A flexDirection padrão é column, não row como muitos layouts web assumem.
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.screen}>
<View style={styles.header}>
<Text style={styles.label}>Cabeçalho (empilhado primeiro)</Text>
</View>
<View style={styles.main}>
<Text style={styles.label}>Conteúdo principal preenche o meio</Text>
</View>
<View style={styles.footer}>
<Text style={styles.label}>Rodapé (empilhado por último)</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, padding: 16 },
header: { padding: 12, backgroundColor: "#dbeafe", borderRadius: 8 },
main: { flex: 1, justifyContent: "center", alignItems: "center", marginVertical: 12 },
footer: { padding: 12, backgroundColor: "#f3f4f6", borderRadius: 8 },
label: { fontWeight: "600" },
});flex: 1 em main faz com que ele consuma o espaço vertical restante entre o cabeçalho e o rodapéjustifyContent alinha ao longo do eixo principal (vertical aqui); alignItems ao longo do eixo transversal (horizontal)flexDirection: "row" quando precisar de irmãos lado a lado - coberto em profundidade no guia de flexboxRelacionado: Mergulho Profundo em Flexbox - direção, crescimento/encolhimento flexível e receitas comuns
Espaçamento no React Native usa o mesmo modelo de caixa do CSS, com atalhos e props por borda - todos os números são dp.
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.screen}>
<View style={styles.card}>
<Text style={styles.title}>Primitivos de Espaçamento</Text>
<View style={styles.row}>
<View style={styles.chip}>
<Text>A</Text>
</View>
<View style={styles.chip}>
<Text>B</Text>
</View>
<View style={styles.chip}>
<Text>C</Text>
</View>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, padding: 16, backgroundColor: "#f9fafb" },
card: {
padding: 20,
marginBottom: 16,
backgroundColor: "#fff",
borderRadius: 12,
},
title: { marginBottom: 12, fontWeight: "600" },
row: { flexDirection: "row", gap: 8 },
chip: {
paddingHorizontal: 12,
paddingVertical: 8,
backgroundColor: "#e0e7ff",
borderRadius: 16,
},
});padding afeta o interior do elemento; margin empurra para longe dos irmãos e das bordas do paipaddingHorizontal / paddingVertical (ou marginTop, etc.) quando as bordas precisarem de valores diferentesgap (RN 0.71+) adiciona espaço entre filhos flexíveis sem margem em cada filho - prefira-o em linhas e gradesRelacionado: Escala de Tipografia e Carregamento de Fontes - altura da linha e espaçamento de texto legível | Melhores Práticas de Estilização - escalas de espaçamento e tokens
Passe um array para style para sobrepor estilos base, de estado e de sobrescrita - entradas posteriores vencem em chaves conflitantes.
import { useState } from "react";
import { View, Text, Pressable, StyleSheet } from "react-native";
export default function App() {
const [active, setActive] = useState(false);
return (
<View style={styles.container}>
<Pressable onPress={() => setActive((v) => !v)}>
<View style={[styles.tab, active && styles.tabActive]}>
<Text style={[styles.tabText, active && styles.tabTextActive]}>
{active ? "Ativo" : "Inativo"}
</Text>
</View>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
tab: {
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 20,
backgroundColor: "#e5e7eb",
},
tabActive: { backgroundColor: "#2563eb" },
tabText: { color: "#374151", fontWeight: "500" },
tabTextActive: { color: "#fff" },
});style={[styles.base, condition && styles.modifier]} é o padrão para UI orientada por estadofalse, undefined) são ignoradas - não há necessidade de filtrar o array manualmente[styles.a, styles.b] significa que b sobrescreve a em chaves duplicadasPressable também aceita uma função de estilo ({ pressed }) => [...] para feedback de toque - combine com arrays para estados complexosRelacionado: Mergulho Profundo em Flexbox - alinhando layouts compostos | Modo Escuro e Esquemas de Cores - arrays de estilo cientes de temas
Leia a preferência de aparência do sistema do usuário e troque cores de fundo e texto sem uma biblioteca de temas separada.
import { View, Text, useColorScheme, StyleSheet } from "react-native";
const palette = {
light: { bg: "#ffffff", text: "#111827", card: "#f3f4f6" },
dark: { bg: "#111827", text: "#f9fafb", card: "#1f2937" },
};
export default function App() {
const scheme = useColorScheme() ?? "light";
const colors = palette[scheme];
return (
<View style={[styles.screen, { backgroundColor: colors.bg }]}>
<View style={[styles.card, { backgroundColor: colors.card }]}>
<Text style={[styles.title, { color: colors.text }]}>
Esquema do sistema: {scheme}
</Text>
<Text style={{ color: colors.text, opacity: 0.7 }}>
Alterne claro/escuro nas configurações do dispositivo para ver esta atualização.
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, padding: 16, justifyContent: "center" },
card: { padding: 20, borderRadius: 12 },
title: { fontSize: 18, fontWeight: "600", marginBottom: 8 },
});useColorScheme() retorna "light", "dark", ou null - use "light" como padrão quando for nulo (algumas configurações do Android)palette simples é suficiente para começar; extraia tokens para um módulo compartilhado à medida que o aplicativo cresce{ color: colors.text }) são aceitáveis aqui porque o esquema muda raramenteRelacionado: Modo Escuro e Esquemas de Cores - paletas dinâmicas,
Appearancee sincronização com o sistema
Mantenha o conteúdo da tela livre de entalhes, barras de status e indicadores de início envolvendo a raiz com SafeAreaView.
import { Text, StyleSheet } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
export default function App() {
return (
<SafeAreaView style={styles.safe}>
<Text style={styles.title}>Layout de Área Segura</Text>
<Text style={styles.body}>
O conteúdo respeita as margens do sistema no iOS e o modo tela cheia no Android.
</Text>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1, padding: 20, backgroundColor: "#fff" },
title: { fontSize: 22, fontWeight: "bold", marginBottom: 8 },
body: { fontSize: 15, lineHeight: 22, color: "#4b5563" },
});react-native-safe-area-context, não de react-native - o SafeAreaView principal é apenas para iOS e limitadoSafeAreaProvider - necessário para que os valores de margem sejam resolvidosflex: 1 em SafeAreaView permite que os filhos preencham a área ajustada pela margem, não a tela brutauseSafeAreaInsets() quando apenas algumas bordas precisarem de padding (por exemplo, uma imagem de cabeçalho de tela cheia)Relacionado: Áreas Seguras e Entalhes - margens por borda e Android tela cheia no RN 0.86
iOS e Android renderizam sombras de forma diferente - Platform.select mantém um único objeto de estilo com ramificações por plataforma.
import { View, Text, Platform, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.screen}>
<View style={styles.card}>
<Text style={styles.title}>Cartão ciente da plataforma</Text>
<Text style={styles.body}>
iOS usa props de sombra; Android usa elevação.
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: "center",
padding: 24,
backgroundColor: "#f3f4f6",
},
card: {
backgroundColor: "#fff",
borderRadius: 16,
padding: 20,
...Platform.select({
ios: {
shadowColor: "#000",
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.12,
shadowRadius: 8,
},
android: { elevation: 6 },
}),
},
title: { fontSize: 18, fontWeight: "600", marginBottom: 8 },
body: { fontSize: 14, color: "#6b7280", lineHeight: 20 },
});Platform.select retorna o valor correspondente para o sistema operacional atual - espalhe-o em objetos StyleSheet de forma limpashadowColor, shadowOffset, shadowOpacity, shadowRadius juntas; Android usa elevationPlatform.OS funciona para pequenos ramos JSX; prefira Platform.select quando apenas os valores de estilo diferemRelacionado: Sombras, Elevação e Bordas - linhas finas, overflow e limites de elevação
Derive valores de layout da largura atual da janela para que a rotação e tablets se reajustem sem larguras de pixel codificadas.
import { View, Text, useWindowDimensions, StyleSheet } from "react-native";
export default function App() {
const { width } = useWindowDimensions();
const columns = width >= 768 ? 3 : 2;
const gap = 12;
const horizontalPadding = 32;
const tileSize =
(width - horizontalPadding - gap * (columns - 1)) / columns;
return (
<View style={styles.container}>
<Text style={styles.heading}>
{columns} colunas · {Math.round(width)}px de largura
</Text>
<View style={[styles.grid, { gap }]}>
{Array.from({ length: 6 }, (_, i) => (
<View
key={i}
style={[styles.tile, { width: tileSize, height: tileSize }]}
>
<Text>Tile {i + 1}</Text>
</View>
))}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 },
heading: { fontSize: 16, fontWeight: "600", marginBottom: 16 },
grid: { flexDirection: "row", flexWrap: "wrap" },
tile: {
backgroundColor: "#e0e7ff",
borderRadius: 8,
justifyContent: "center",
alignItems: "center",
},
});useWindowDimensions re-renderiza na rotação e redimensionamento - ao contrário do snapshot único de Dimensions.get("window")width menos o padding e os gaps - dimensões numéricas evitam surpresas com porcentagens em grades flexíveisTABLET = 768) compartilhadas entre telas para um comportamento adaptativo consistenteRelacionado: Layout Responsivo e Adaptativo - tablets, dobráveis e visualização dividida
Combine StyleSheet, useColorScheme e um pequeno módulo de tokens em um padrão reutilizável que os aplicativos de produção usam antes de recorrer a uma biblioteca de estilização.
import { View, Text, useColorScheme, StyleSheet } from "react-native";
const spacing = { sm: 8, md: 16, lg: 24 } as const;
const themes = {
light: {
screen: "#f9fafb",
card: "#ffffff",
text: "#111827",
muted: "#6b7280",
border: "#e5e7eb",
},
dark: {
screen: "#111827",
card: "#1f2937",
text: "#f9fafb",
muted: "#9ca3af",
border: "#374151",
},
} as const;
export default function App() {
const scheme = useColorScheme() ?? "light";
const theme = themes[scheme];
return (
<View style={[styles.screen, { backgroundColor: theme.screen }]}>
<View
style={[
styles.card,
{ backgroundColor: theme.card, borderColor: theme.border },
]}
>
<Text style={[styles.label, { color: theme.muted }]}>Conta</Text>
<Text style={[styles.value, { color: theme.text }]}>alex@example.com</Text>
<View style={[styles.divider, { backgroundColor: theme.border }]} />
<Text style={[styles.label, { color: theme.muted }]}>Plano</Text>
<Text style={[styles.value, { color: theme.text }]}>Pro · renova em 1 ago</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, justifyContent: "center", padding: spacing.md },
card: {
borderRadius: 12,
borderWidth: 1,
padding: spacing.lg,
},
label: { fontSize: 13, marginBottom: spacing.sm },
value: { fontSize: 16, fontWeight: "600", marginBottom: spacing.md },
divider: { height: StyleSheet.hairlineWidth, marginBottom: spacing.md },
});spacing, themes) ficam ao lado ou acima dos componentes - layout estático em StyleSheet, cores semânticas do objeto de temaStyleSheet.hairlineWidth é a linha visível mais fina no dispositivo atual - use-a para divisores em vez de codificar 1as const para que as chaves permaneçam estreitas e erros de digitação falhem em tempo de compilaçãotheme.ts e alinhe-os com seu sistema de design - veja as melhores práticas antes de adotar styled-components ou NativeWindRelacionado: Melhores Práticas de Estilização - nomenclatura de tokens e trade-offs de bibliotecas | Modo Escuro e Esquemas de Cores - sincronizando navegação e barra de status com o tema
Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026