Até a versão 0.75, estilizar sombras no React Native era um exercício de paciência: um conjunto de props só para iOS (shadowColor, shadowOffset, shadowOpacity, shadowRadius), mais a prop elevation para Android, que produzia um resultado visual completamente diferente e não aceitava cor customizada. Com o React Native 0.76, a Nova Arquitetura passou a suportar duas props de estilo inspiradas diretamente no CSS da web: boxShadow e filter, finalmente unificando sombras e efeitos gráficos entre as duas plataformas.
O jeito antigo (props separadas por plataforma)
Para ter uma sombra parecida em iOS e Android, era preciso duplicar a lógica de estilo e aceitar que o resultado nunca seria idêntico:
<View
style={{
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 6,
elevation: 8, // comportamento diferente no Android
}}
/>
Além da duplicação, essa abordagem não funcionava em Views sem cor de fundo no Android e não suportava sombra interna (inset) nem spread.
Como funciona o boxShadow
A prop boxShadow aceita uma string no mesmo formato do CSS box-shadow da web, ou um objeto (ou array de objetos, para múltiplas sombras) com as mesmas informações:
// Forma string, igual ao CSS da web
<View style={{ boxShadow: '5px 5px 10px 0px rgba(255, 0, 0, 0.5)' }} />
// Forma objeto, mais fácil de compor com variáveis
<View
style={{
boxShadow: {
offsetX: 5,
offsetY: 5,
blurRadius: 10,
spreadDistance: 0,
color: 'rgba(255, 0, 0, 0.5)',
},
}}
/>
As duas formas produzem o mesmo resultado. A forma objeto é mais prática quando os valores vêm de um tema ou de props do componente, já que evita montar a string manualmente.
Sombras múltiplas e sombra interna
Passando um array, dá para empilhar mais de uma sombra na mesma View — e usando inset: true, a sombra passa a ser projetada para dentro do elemento em vez de para fora:
<View
style={{
borderRadius: 12,
boxShadow: [
{ offsetX: 0, offsetY: 2, blurRadius: 4, color: 'rgba(0,0,0,0.2)' },
{ offsetX: 0, offsetY: 0, blurRadius: 6, spreadDistance: -2, color: 'rgba(0,0,0,0.3)', inset: true },
],
}}
/>
Como funciona o filter
A prop filter aplica efeitos gráficos ao componente inteiro, com a mesma lista de funções do CSS filter da web: brightness, contrast, grayscale, hueRotate, invert, opacity, saturate, sepia, blur e dropShadow. Também aceita string ou array de objetos:
// Forma string
<Image source={foto} style={{ filter: 'grayscale(1) brightness(0.8)' }} />
// Forma array de objetos, combinando múltiplos efeitos
<Image
source={foto}
style={{
filter: [{ grayscale: 1 }, { brightness: 0.8 }, { blur: 2 }],
}}
/>
Esse exemplo deixa a imagem em tons de cinza, reduz o brilho e aplica um leve desfoque — tudo sem precisar de uma lib nativa de processamento de imagem ou de capturar a view com react-native-view-shot para editar os pixels.
dropShadow: sombra que segue a silhueta
Diferente de boxShadow, que projeta uma sombra retangular (respeitando borderRadius), a função dropShadow do filter gera uma sombra que acompanha o contorno real dos pixels não transparentes — ideal para ícones e imagens com fundo transparente:
<Image
source={require('./logo-transparente.png')}
style={{
filter: [{ dropShadow: '0 4px 6px rgba(0, 0, 0, 0.4)' }],
}}
/>
Casos de uso
- Cards, modais e botões com sombra consistente entre iOS e Android, sem gambiarra de
elevation. - Estados desabilitados usando
filter: 'grayscale(1) opacity(0.5)'em vez de trocar cores manualmente. - Efeito de carregamento (skeleton/placeholder) com
filter: 'blur(8px)'sobre uma miniatura de baixa resolução. - Sombra que acompanha a silhueta de ícones com transparência, via
dropShadow.
Cuidados
As duas props só funcionam com a Nova Arquitetura habilitada (Fabric) — em apps ainda rodando na arquitetura antiga, elas são ignoradas silenciosamente. blur e dropShadow dentro de filter exigem Android 12+; sombras normais via boxShadow pedem Android 9+, e sombras internas (inset: true) pedem Android 10+. A cor padrão da sombra também diverge da web: no React Native, sem especificar color, o padrão é preto, enquanto no CSS da web o padrão herda a cor do texto do elemento.
Compatibilidade
boxShadow e filter foram introduzidos no React Native 0.76 (outubro de 2024), exigindo a Nova Arquitetura habilitada no projeto. Não há como usá-los na arquitetura antiga (bridge clássica) nem via Expo Go em versões anteriores ao suporte completo da Nova Arquitetura no SDK correspondente.
Conclusão
Com boxShadow e filter, o React Native encerra anos de divergência entre as props de sombra do iOS e a elevation do Android, adotando a sintaxe já conhecida do CSS da web. É uma das mudanças mais práticas da Nova Arquitetura: menos código condicional por plataforma e efeitos visuais que antes exigiam bibliotecas nativas extras.
0 Comentário
Deixe seu Comentário!
Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.