Guia completo de sombras CSS: box-shadow, drop-shadow e text-shadow explicados
Domine as três técnicas de sombra CSS — sintaxe, parâmetros, diferenças de renderização, padrões reais e implicações de performance.
Sombras são uma das ferramentas mais simples no CSS, mas a maioria dos tutoriais apenas arranha a superfície. Este guia cobre os três mecanismos em profundidade — sintaxe, parâmetros, diferenças de renderização, casos de uso reais e implicações de performance — para que você sempre escolha a técnica certa.
Por que o CSS tem três propriedades de sombra?
Cada mecanismo de sombra existe para resolver um problema diferente. Eles surgiram em momentos distintos da história do CSS e têm alvos de renderização fundamentalmente diferentes:
box-shadow— sombras para caixas retangulares (o box model CSS). Disponível desde o CSS 2.1, padronizado no CSS3.filter: drop-shadow()— sombras que seguem a forma visível real de um elemento, incluindo transparência. Parte da especificação CSS Filter Effects Level 1.text-shadow— sombras aplicadas diretamente aos contornos de glifos. Tecnicamente a mais antiga das três, introduzida no CSS 2, brevemente removida e re-padronizada no CSS3.
A confusão surge porque as três produzem o que o olho humano percebe como "uma sombra", mas o motor de renderização as trata em fases completamente diferentes do pipeline de pintura.
Use box-shadow para elementos de UI com fundos sólidos. Use drop-shadow para PNGs, SVGs ou qualquer coisa com transparência. Use text-shadow exclusivamente em texto.
box-shadow: o cavalo de batalha
Desenha uma ou mais sombras atrás (ou dentro) do border box de um elemento — a propriedade de sombra mais versátil e amplamente utilizada.
Sintaxe
box-shadow: [inset] offset-x offset-y [blur-radius] [spread-radius] color; Cada valor faz exatamente uma coisa:
| Parâmetro | Padrão | O que controla |
|---|---|---|
inset | omitido (externo) | Desenha a sombra dentro do elemento em vez de atrás |
offset-x | obrigatório | Distância horizontal. Positivo = direita, negativo = esquerda |
offset-y | obrigatório | Distância vertical. Positivo = baixo, negativo = cima |
blur-radius | 0 | Quantidade de desfoque gaussiano. Maior = mais suave e difuso |
spread-radius | 0 | Expande (+) ou contrai (–) a sombra antes do desfoque |
color | currentColor | Cor da sombra — sempre use rgba() ou hsla() para realismo |
O spread radius: o parâmetro subutilizado
A maioria dos desenvolvedores usa offset + blur e para por aí. O spread radius desbloqueia uma classe de efeitos completamente diferente. Com spread: 0 e blur: 0 torna-se uma borda CSS perfeita e empilhável que não afeta o layout:
/* Layered outline rings — no layout impact */
box-shadow:
0 0 0 4px rgba(201,184,154,.4),
0 0 0 8px rgba(201,184,154,.1); Com spread negativo você pode transformar uma sombra difusa em uma direcional que aparece apenas abaixo de um elemento:
/* Shadow only at the bottom — more realistic */
box-shadow: 0 12px 24px -8px rgba(0,0,0,.6); Exemplos ao vivo
4px 4px 8px rgba(0,0,0,.7) 0 0 0 4px accent inset 0 4px 12px 0 2px 4px + 0 8px 24px + ring 0 0 24px + 0 0 48px light + dark inset pair backdrop-blur + shadow Sombras múltiplas: a ordem importa
Você pode empilhar um número ilimitado de sombras com uma lista separada por vírgulas. O renderizador as processa da frente para trás — a primeira sombra da lista fica no topo. Isso permite combinar sombras ambientes e direcionais para profundidade natural em temas claro e escuro.
/* Three-layer system used in serious design systems */
box-shadow:
0 1px 2px rgba(0,0,0,.3), /* close shadow: sharp, small */
0 4px 16px rgba(0,0,0,.25), /* mid shadow: soft ambient */
0 0 0 1px rgba(255,255,255,.05); /* subtle highlight ring */ Sombras inset: profundidade e estados pressionados
A palavra-chave inset move a sombra para dentro da borda do elemento. A direção do offset se inverte intuitivamente: um offset Y positivo coloca a sombra ao longo da borda interna superior, como se a luz viesse de cima. Essencial para botões pressionados, inputs em relevo e neumorfismo:
/* Input focus state — depth without a visible border */
input:focus {
box-shadow:
inset 0 2px 6px rgba(0,0,0,.5),
0 0 0 2px rgba(201,184,154,.4);
} Ferramenta gratuita Gerador Box Shadow Ajuste os parâmetros e copie o CSS pronto para produção filter: drop-shadow() — sombras que seguem a forma
filter: drop-shadow() não é uma propriedade — é uma função de filtro CSS. Os filtros são aplicados após a pintura, operando nos pixels finalmente renderizados de um elemento e seus descendentes. Essa distinção tem duas consequências importantes:
- A sombra segue o contorno visível real, respeitando a transparência alpha em PNGs e a forma dos caminhos SVG.
- O filtro afeta toda a subárvore, incluindo os filhos. Isso significa que funciona automaticamente em grupos de elementos.
Sintaxe
filter: drop-shadow(offset-x offset-y blur-radius color); Atenção: sem spread-radius e sem palavra-chave inset. A especificação os omitiu deliberadamente. Se precisar de spread em uma sombra que segue a forma, empilhe duas chamadas drop-shadow() com raios de desfoque diferentes.
Onde box-shadow falha e drop-shadow brilha
Imagine um logo PNG transparente sobre um fundo colorido. Aplique box-shadow e você obterá uma sombra retangular ao redor do bounding box invisível — a sombra vaza nas áreas transparentes. Aplique drop-shadow() e a sombra abraça a forma visível real do logo.
A mesma lógica se aplica a:
- Elementos SVG — caminhos, polígonos, formas compostas
- CSS clip-path — a sombra segue o limite do clip
- Elementos rotacionados ou transformados — a sombra segue corretamente a forma pós-transformação
- Grupos de componentes — um filtro no pai cria sombra em todos os filhos como unidade
/* SVG icon with proper shadow */
.icon-wrapper {
filter: drop-shadow(0 4px 8px rgba(0,0,0,.6));
}
/* PNG logo — shadow follows logo shape, not its bounding box */
.logo {
filter: drop-shadow(2px 4px 12px rgba(0,0,0,.5));
}
/* Stacked for a glow effect on an irregular shape */
.neon-svg {
filter:
drop-shadow(0 0 6px rgba(201,184,154,.8))
drop-shadow(0 0 20px rgba(201,184,154,.4));
} O compromisso-chave: contexto de empilhamento
Aplicar filter cria um novo contexto de empilhamento e uma nova camada de composição. Normalmente tudo bem, mas significa que o elemento não pode mais se sobrepor corretamente a outras camadas de composição — o que ocasionalmente causa problemas de z-index. Se isso ocorrer, considere se box-shadow pode aproximar o efeito.
text-shadow: profundidade tipográfica
text-shadow é aplicado exclusivamente aos contornos de glifos do texto — não ao box do elemento. É pintado na mesma fase que o texto, atrás dos glifos, sendo a escolha certa quando se deseja profundidade ou legibilidade em elementos tipográficos.
Sintaxe
text-shadow: offset-x offset-y [blur-radius] color; Comparado ao box-shadow, não há spread-radius nem inset. Sombras múltiplas são separadas por vírgulas, com a mesma ordem frente-para-trás.
Exemplos ao vivo
2px 2px 4px rgba(0,0,0,.8) 0 0 10px + 0 0 30px light + dark offset pair hard double offset Casos de uso comuns
Legibilidade sobre imagens: Um sutil text-shadow: 0 1px 3px rgba(0,0,0,.6) torna o texto branco legível sobre fotografias brilhantes sem precisar de um overlay escuro.
Tipografia neon/glow: Empilhe duas sombras com offset zero e raios de desfoque crescentes. A sombra interna cria o núcleo intenso, a externa cria o brilho atmosférico:
.neon {
color: #c9b89a;
text-shadow:
0 0 8px rgba(201,184,154,.9),
0 0 24px rgba(201,184,154,.5),
0 0 60px rgba(201,184,154,.2);
} Letterpress / relevo: Combine uma sombra clara em cima-esquerda com uma escura em baixo-direita. A direção determina se o texto parece em relevo ou afundado:
/* Raised (light = up-left, dark = down-right) */
text-shadow: -1px -1px 0 rgba(255,255,255,.15), 1px 1px 0 rgba(0,0,0,.6);
/* Recessed (reversed) */
text-shadow: 1px 1px 0 rgba(255,255,255,.1), -1px -1px 0 rgba(0,0,0,.5); Sombra dura (estilo retrô/quadrinhos): Sem blur, offset maior, sombras duras empilhadas:
.retro {
text-shadow: 3px 3px 0 #7a5c38, 6px 6px 0 rgba(0,0,0,.25);
} Ferramenta gratuita Gerador Text Shadow Crie e exporte efeitos text-shadow com pré-visualização ao vivo Comparação lado a lado
| Característica | box-shadow | drop-shadow() | text-shadow |
|---|---|---|---|
| Alvo | Box model do elemento | Forma de pixels renderizados | Contornos de glifos de texto |
| Respeita transparência | Não — ignora alpha | Sim — segue a forma | N/A (somente texto) |
| spread-radius | Sim | Não | Não |
| Palavra-chave inset | Sim | Não | Não |
| Camadas múltiplas | Sim, separadas por vírgula | Sim, funções encadeadas | Sim, separadas por vírgula |
| Contexto de empilhamento | Sem novo contexto | Cria novo contexto | Sem novo contexto |
| Aplica-se aos filhos | Não | Sim (subárvore inteira) | Não |
| Funciona em SVG | Apenas bounding box | Sim, por caminho | N/A |
| Animação CSS | Animável | Animável | Animável |
| Composição GPU | Frequentemente, em camadas promovidas | Sim, sempre | Raramente |
A pergunta que determina qual usar
Pergunte-se: o elemento tem um fundo retangular e opaco? Se sim, use box-shadow — mais fácil de raciocinar e sem efeitos colaterais no contexto de empilhamento. Se não (PNG transparente, SVG, forma irregular, clip-path), use drop-shadow(). Se o alvo é texto, use text-shadow.
Receitas e padrões para produção
Sistema de elevação (estilo Material)
Em vez de hardcodar valores de sombra por todo o codebase, defina uma escala de elevação como propriedades CSS personalizadas. Isso torna a profundidade global consistente e fácil de atualizar:
:root {
--shadow-1: 0 1px 2px rgba(0,0,0,.4);
--shadow-2: 0 2px 6px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.3);
--shadow-3: 0 4px 16px rgba(0,0,0,.3), 0 2px 4px rgba(0,0,0,.3);
--shadow-4: 0 8px 32px rgba(0,0,0,.28), 0 4px 8px rgba(0,0,0,.25);
--shadow-5: 0 16px 48px rgba(0,0,0,.25), 0 8px 16px rgba(0,0,0,.2);
}
.card { box-shadow: var(--shadow-2); }
.card:hover { box-shadow: var(--shadow-4); transition: box-shadow .2s ease; }
.modal { box-shadow: var(--shadow-5); } Sombras coloridas
Uma das técnicas mais subutilizadas: em vez de sombras pretas, tinja a sombra com a cor dominante do elemento. Fica mais natural em temas claros e escuros e cria uma qualidade similar ao glow sem parecer agressiva:
/* Button with colored shadow matching brand color */
.btn-primary {
background: #c9b89a;
box-shadow: 0 4px 20px rgba(201,184,154,.4), 0 2px 6px rgba(201,184,154,.3);
}
.btn-primary:hover {
box-shadow: 0 6px 28px rgba(201,184,154,.55), 0 3px 8px rgba(201,184,154,.4);
} Glassmorfismo com sombra
O glassmorfismo requer uma interação cuidadosamente calibrada entre backdrop-filter, fundo translúcido, borda semi-transparente e box-shadow para separar o card do fundo:
.glass-card {
background: rgba(255, 255, 255, 0.06);
backdrop-filter: blur(16px) saturate(1.2);
-webkit-backdrop-filter: blur(16px) saturate(1.2);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px;
box-shadow:
0 8px 32px rgba(0,0,0,.4), /* ambient depth */
inset 0 1px 0 rgba(255,255,255,.08); /* top highlight */
} PixCode Glassmorphism Generator exporta o CSS completo incluindo prefixos vendor.
Anéis de foco com box-shadow
Substituir o outline padrão do navegador por box-shadow dá controle total sobre o estilo mantendo a acessibilidade. O truque é usar uma sombra apenas de spread com blur 0:
:focus-visible {
outline: none;
box-shadow:
0 0 0 2px var(--bg), /* gap between element and ring */
0 0 0 4px rgba(201,184,154,.7); /* visible ring */
} Neumorfismo
O neumorfismo usa pares de sombras inset e outer derivadas da cor de fundo. O elemento, a sombra e o fundo devem usar tons estreitamente relacionados — contraste extremo quebra a ilusão:
/* Element bg = slightly lighter than page bg */
.neumorphic {
background: #1c1c1c;
border-radius: 16px;
box-shadow:
8px 8px 16px #0a0a0a, /* dark shadow: down-right */
-8px -8px 16px #2e2e2e; /* light shadow: up-left */
}
.neumorphic.pressed {
box-shadow:
inset 4px 4px 10px #0a0a0a,
inset -4px -4px 10px #2e2e2e;
} Considerações de performance
Sombras são uma das operações de renderização com que os desenvolvedores mais se preocupam, frequentemente sem razão. Veja o que realmente acontece:
✓ Caminhos rápidos
box-shadow em camadas de composição GPU (position:fixed, will-change:transform). filter: drop-shadow() é sempre acelerado por GPU. Animar box-shadow via transições CSS em elementos promovidos.
✗ Caminhos lentos
Animar box-shadow em elementos não promovidos aciona layout + paint em cada frame. Raios de blur grandes em filter: drop-shadow() são custosos. text-shadow com blur muito grande em muitos elementos.
Ao animar sombras
O padrão mais seguro para sombras animadas (elevações no hover, estados de carregamento) é promover o elemento primeiro e depois transicionar a sombra:
.card {
will-change: transform; /* promote to compositing layer */
transform: translateZ(0); /* trigger layer in older browsers */
transition: box-shadow .2s ease, transform .2s ease;
box-shadow: var(--shadow-2);
}
.card:hover {
transform: translateY(-2px); /* move on GPU — free */
box-shadow: var(--shadow-4); /* re-composite — also fast */
} Não aplique will-change indiscriminadamente — cada camada promovida consome memória GPU. Use apenas em elementos que realmente vão animar, e remova-o quando a animação terminar se adicionado via JavaScript.
Performance: blur-radius vs spread-radius
Aumentar blur-radius é mais custoso que aumentar spread-radius, pois o blur requer uma convolução gaussiana que escala com a área em pixels. Uma sombra com spread: 10px, blur: 2px é mais barata que spread: 0, blur: 12px para a mesma pegada visual.
Geradores de sombra interativos no PixCode.io
As três técnicas de sombra têm geradores interativos dedicados no PixCode — ajuste parâmetros com sliders, veja o resultado ao vivo e copie o CSS pronto para produção com um clique.