Sombra projetada para a imagem PNG em CSS

211

Eu tenho uma imagem PNG, que tem forma livre (não quadrada).

Preciso aplicar o efeito de sombra projetada a esta imagem.

A abordagem padrão ...

-o-box-shadow:      12px 12px 29px #555;
-icab-box-shadow:   12px 12px 29px #555;
-khtml-box-shadow:  12px 12px 29px #555;
-moz-box-shadow:    12px 12px 29px #555;
-webkit-box-shadow: 12px 12px 29px #555;
box-shadow:         12px 12px 29px #555;

... exibe sombras para esta imagem, como se fosse um quadrado. Então, vejo minha imagem e sombra quadrada, que não seguem a forma do objeto, exibida na imagem.

Existe alguma maneira de fazer isso corretamente?

AntonAL
fonte

Respostas:

261

Um pouco atrasado para a festa, mas sim, é totalmente possível criar sombreamentos dinâmicos "verdadeiros" em torno de PNGs com máscara alfa, usando uma combinação de filtros de sombreamento (para Webkit), SVG (para Firefox) e filtros DX para IE.

.shadowed {
    -webkit-filter: drop-shadow(12px 12px 25px rgba(0,0,0,0.5));
    filter: url(#drop-shadow);
    -ms-filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
    filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
}
<!-- HTML elements here -->

<svg height="0" xmlns="http://www.w3.org/2000/svg">
    <filter id="drop-shadow">
        <feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
        <feOffset dx="12" dy="12" result="offsetblur"/>
        <feFlood flood-color="rgba(0,0,0,0.5)"/>
        <feComposite in2="offsetblur" operator="in"/>
        <feMerge>
            <feMergeNode/>
            <feMergeNode in="SourceGraphic"/>
        </feMerge>
    </filter>
</svg>

Algumas comparações entre sombra verdadeira e sombra de caixa e um artigo sobre a técnica que acabei de descrever .

Eu espero que isso ajude!

Dudley Storey
fonte
1
Ainda mais tarde para a festa, mas um para o CSS cross-plateform filterpropriedade ... Embora, eu não acho que seja necessário as tags HTML SVG, qualquer PNG com alfa canal irá fazer o truque
Guillaume
2
Dudley Storey está certo. Sem o SVG, a sombra não aparece no Firefox. @AntonAL poderia aceitar esta resposta.
Javsmo # 15/13
5
Os filtros DX não funcionam mais no IE ... Existe alguma nova solução para o IE? msdn.microsoft.com/pt-br/library/hh801215(v=vs.85).aspx
tb11 18/11/15
2
Atualmente, o Firefox suporta, filter: drop-shadow(x y blur color); portanto, o truque SVG não deve mais ser necessário.
Raptor007
11
Não podemos todos concordar que o IE deveria ter sido jogado na pilha de lixo anos atrás? O Edge é um pouco melhor, mas a vaca sagrada M $ você propositadamente voltou o desenvolvimento de software para a idade das trevas com o IE? Que abominação.
RyanNerd
217

Sim, é possível usar filter: dropShadow(x y blur? spread? color?), em CSS ou em linha:

img {
  width: 150px;
  -webkit-filter: drop-shadow(5px 5px 5px #222);
  filter: drop-shadow(5px 5px 5px #222);
}
<img src="https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png">

<img src="https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png" style="-webkit-filter: drop-shadow(5px 5px 5px #222); filter: drop-shadow(5px 5px 5px #222);">

Abdul
fonte
8
No IE support ... :(
CF
10
O IE deve acompanhar os horários: P
Bryant Jackson
6
-webkit-filter não é mais necessário
Brett Donald
11
2019: o que é o IE? : P
evilReiko
36

Se você tiver mais de 100 imagens nas quais deseja sombras projetadas, sugiro usar o programa de linha de comando ImageMagick . Com isso, você pode aplicar sombras projetadas a 100 imagens apenas digitando um comando! Por exemplo:

for i in "*.png"; do convert $i '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage "shadow/$i"; done

O comando acima (shell) pega cada arquivo .png no diretório atual, aplica uma sombra projetada e salva o resultado no diretório sombra /. Se você não gosta das sombras projetadas, pode ajustar muito os parâmetros; comece observando a documentação em busca de sombras e as instruções gerais de uso têm muitos exemplos interessantes de coisas que podem ser feitas nas imagens.

Se você mudar de ideia no futuro sobre a aparência das sombras projetadas - é apenas um comando para gerar novas imagens com parâmetros diferentes :-)

psmears
fonte
22
Embora seja uma solução, não responde à pergunta!
leo
6
O solicitante está tentando fazer com que o navegador renderize a sombra, não execute scripts no servidor que pode criar sombras. Esta é uma informação útil, mas não o mesmo espaço problemático.
SG1
Algumas notas para que isso funcione: 1. Você precisa criar o diretório shadow antes de executar este comando (como em mkdir shadow) 2. $ideve ser citado (como em "$i") ou ele engasgará se uma imagem tiver um espaço em seu nome de arquivo:for i in *.png; do convert "$i" '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage shadow/"$i".png; done
Andrew Macheret
2
3. Os arquivos resultantes serão nomeados filename.png.png. Aqui está uma versão totalmente funcional:for i in *.png; do convert "$i" '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage shadow/"$i"; done
Andrew Macheret
@AndrewMacheret: Bons pontos - embora note que isso deve ser uma ilustração do que pode ser feito, em vez de um programa totalmente funcional! Corrigi o sufixo .png duplo e as aspas; a coisa diretório eu me sinto só iria ficar no caminho ...
psmears
34
img {
  -webkit-filter: drop-shadow(5px 5px 5px #222222);
  filter: drop-shadow(5px 5px 5px #222222);
}

Isso funcionou muito bem para mim. Uma coisa a ser observada no IE é que você precisa da cor completa (# 222222) em que três caracteres não funcionam.

Jaclyn U
fonte
29

Como Dudley mencionou em sua resposta isso é possível com o filtro CSS drop-shadow para webkit, SVG para Firefox e filtros DirectX para Internet Explorer 9-.

Um passo adiante é alinhar o SVG, eliminando a solicitação extra:

.shadowed {
    -webkit-filter: drop-shadow(12px 12px 25px rgba(0,0,0,0.5));
    filter: url("data:image/svg+xml;utf8,<svg height='0' xmlns='http://www.w3.org/2000/svg'><filter id='drop-shadow'><feGaussianBlur in='SourceAlpha' stdDeviation='4'/><feOffset dx='12' dy='12' result='offsetblur'/><feFlood flood-color='rgba(0,0,0,0.5)'/><feComposite in2='offsetblur' operator='in'/><feMerge><feMergeNode/><feMergeNode in='SourceGraphic'/></feMerge></filter></svg>#drop-shadow");
    -ms-filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
    filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
}
Karl Horky
fonte
1
Funciona bem .. melhor do que se eu definir o SVG dentro das tags HTML. (firefox)
Oki Erie Rinaldi
18

Adicione borda com raio na sua classe se for um bloco. porque, por padrão, a sombra será aplicada na borda do bloco, mesmo que sua imagem tenha um canto arredondado.

border-radius: 4px;

altere o raio da borda de acordo com o canto da sua imagem. Espero que esta ajuda.

anupal
fonte
12

Apenas adicione isto:

-webkit-filter: drop-shadow(5px 5px 5px #fff);
 filter: drop-shadow(5px 5px 5px #fff); 

exemplo:

<img class="home-tab-item-img" src="img/search.png"> 

.home-tab-item-img{
    -webkit-filter: drop-shadow(5px 5px 5px #fff);
     filter: drop-shadow(5px 5px 5px #fff); 
}
Mahmoud Zalt
fonte
6

Aqui está o snippet de código da animação de foco instantâneo pronto para isso:

http://codepen.io/widhi_allan/pen/ltaCq

-webkit-filter: drop-shadow(0px 0px 0px rgba(255,255,255,0.80));
Dmitry Kaigorodov
fonte
diferente de webkit?
Mmm
3

Quando eu postei isso originalmente, não era possível, então esta é a solução alternativa. Agora eu simplesmente sugiro usar outras respostas.

Não há como obter exatamente o contorno da imagem, mas você pode falsificá-lo com uma div por trás da imagem no centro.

Se meu truque não funcionar, você deve cortar a imagem e fazê-lo para todas as pequenas imagens. (quanto mais imagens, mais precisa será a sombra), mas para a maioria das imagens, tudo fica bem com apenas um img.

o que você precisa fazer é colocar uma div wrap em torno do seu img assim

<div id="imgWrap">
    <img id="img" scr="imgLocation">
</div>

então você coloca um divisor vazio dentro do envoltório (isso servirá como sombra)

<div id="imgWrap">
    <div id="shadow"> </div>
    <img id="img" scr="imgLocation">
</div>

e então você deve fazer a sombra aparecer atrás do img com CSS:

#img {
    z-index: 1;
}

#shadow {
    z-index: 0; /*make this value negative if doesnt work*/
    box-shadow: 0 -130px 180px 150px rgba(255, 255, 0, 0.6);
    width: 0;
    height: 0;
}

Agora posicione o imgWrap para posicionar o img original ... para centralizar a sombra do img, você pode mexer nos dois primeiros valores da sombra da caixa, tornando-os negativos ... ou pode posicionar o img e a sombra divs absolutamente tornando img os valores superior e esquerdo = 0 e os valores da sombra div = metade da largura e altura do img, respectivamente.

Se isso parecer horrível, corte seu img e tente novamente.

(Se você não quiser a sombra por trás do img apenas no contorno, precisará torná-lo opaco e agir como se fosse transparente, o que não é tão difícil e você pode comentar e eu explicarei depois)

Xitcod13
fonte
Quando eu respondi, não era possível, acho que agora é. O futuro está aqui!
Xitcod13
2

No meu caso, ele teve que funcionar em navegadores móveis modernos, com uma imagem PNG em diferentes formas e transparência. Criei sombra projetada usando uma duplicata da imagem. Isso significa que eu tenho dois imgelementos da mesma imagem, um em cima do outro (usando position: absolute), e o outro por trás tem as seguintes regras aplicadas:

.image-shadow {
  filter: blur(10px) brightness(-100);
  -webkit-filter: blur(10px) brightness(-100);
  opacity: .5;
}

Isso inclui filtro de brilho para escurecer a imagem de fundo e um filtro de desfoque para transmitir o efeito borrado que a sombra geralmente possui. A opacidade a 50% é então aplicada para amolecê-la.

Isso pode ser aplicado em vários navegadores usando moze msflags.

Exemplo: https://jsfiddle.net/5mLssm7o/

eu faço
fonte
1

Isso não será possível com css - uma imagem é um quadrado e, portanto, a sombra seria a sombra de um quadrado. A maneira mais fácil seria usar o photoshop / gimp ou qualquer outro editor de imagens para aplicar a sombra como um desenho principal.

oezi
fonte
Obrigado pela resposta. Mas adicionar imagens no editor terá problemas no futuro, quando terei> 100 imagens e devo ajustar um pouco as sombras. A melhor solução do meu problema - é adicionar uma imagem de sombra adicional abaixo de cada imagem em questão com o jQuery.
AntonAL
1

Um truque que costumo usar quando preciso apenas de um pouco de sombra (leia: o contorno não deve ser super preciso) é colocar um DIV com um preenchimento radial transparente de 100% a preto a 100% sob a imagem. O CSS para o DIV se parece com:

.shadow320x320{    
        background: -moz-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%, rgba(0,0,0,0.58) 1%, rgba(0,0,0,0) 43%, rgba(0,0,0,0) 100%); /* FF3.6+ */
        background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(0,0,0,0.58)), color-stop(1%,rgba(0,0,0,0.58)), color-stop(43%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0))); /* Chrome,Safari4+ */
        background: -webkit-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */
        background: -o-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* Opera 12+ */
        background: -ms-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* IE10+ */
        background: radial-gradient(ellipse at center, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* W3C */
        filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#94000000', endColorstr='#00000000',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
  }

Isso criará um 'ponto' circular preto desbotado em um DIV de 320x320. Se você escalar a altura ou a largura do DIV, obterá um oval correspondente. Muito bom para criar, por exemplo, sombras sob garrafas ou outras formas cilíndricas.

Existe uma ferramenta absolutamente excelente e super excelente para criar gradientes de CSS aqui:

http://www.colorzilla.com/gradient-editor/

ps: faça um clique de anúncio de cortesia ao usá-lo. (E, não, eu não sou afiliado a isso. Mas o clique de cortesia deve se tornar um hábito, especialmente para as ferramentas que você usa com frequência ... apenas dizendo ... já que estamos todos trabalhando na rede ... )

Livrar Iculous
fonte
Eu poderia visto este olhar bastante agradável quando modificado um pouco
BeachInCalifornia.com
1
"Cortesia no clique do anúncio"? Sério, como enganar os anunciantes é uma coisa boa para a 'Net'? Muitos de nós somos anunciantes, ou somos pagos por eles, portanto, cobrar dos anunciantes anúncios por produtos que você nunca vai comprar é uma coisa realmente desagradável. Se você estiver interessado em um anúncio, clique nele por todos os meios, mas não faça isso!
Alastair
Oh, saia do seu terreno moral, Alastair. O mundo real parece um pouco diferente. "Arrancando anunciantes"? Realmente? LOL - Dá um tempo, cara. Trabalho com publicidade e marketing há quase 30 anos. Colocar o clique de cortesia ímpar não tem nenhuma influência além do suporte aos sites que você usa GRATUITAMENTE. Se você está preocupado com a inflação de prêmios, etc., preocupe-se com as tendências cada vez mais monopolizadoras em todo o setor. É isso que distorce os prêmios de publicidade, não o clique de cortesia.
Rid Iculous
Isso parece horrível em FF e IE
barrypicker
1

Você não pode fazer isso de forma confiável em todos os navegadores. A Microsoft não oferece mais suporte a filtros DX a partir do IE10 +, portanto, nenhuma das soluções aqui funciona totalmente:

https://msdn.microsoft.com/en-us/library/hh801215(v=vs.85).aspx

A única propriedade que funciona de maneira confiável em todos os navegadores é box-shadow, e isso coloca a borda no seu elemento (por exemplo, uma div), resultando em uma borda quadrada:

box-shadow: horizontalOffset verticalOffset blurDistance spreadDistance cor inserção;

por exemplo

box-shadow: -2px 6px 12px 6px #CCCED0;

Se você tiver uma imagem 'quadrada', mas com cantos arredondados uniformes, a sombra projetada funcionará border-radius, para que você sempre possa emular os cantos arredondados da imagem na sua div.

Aqui está a documentação da Microsoft para box-shadow:

https://msdn.microsoft.com/en-us/library/gg589484(v=vs.85).aspx

Chris Halcrow
fonte
Agradeço a resposta direta. Nenhum dos exemplos acima funciona para mim.
barrypicker