Ombre portée pour image PNG en CSS


211

J'ai une image PNG, qui a une forme libre (non carrée).

Je dois appliquer un effet d'ombre portée à cette image.

L'approche standard ...

-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;

... affiche des ombres pour cette image, comme si c'était un carré. Donc, je vois mon image et mon ombre carrée, qui ne suit pas la forme de l'objet, affichée dans l'image.

Existe-t-il un moyen de le faire correctement?

Réponses:


261

Un peu tard pour la fête, mais oui, il est totalement possible de créer de "vraies" ombres dynamiques autour des PNG masqués alpha, en utilisant une combinaison de filtres dropshadow (pour Webkit), SVG (pour Firefox) et DX pour 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>

Quelques comparaisons entre la vraie ombre portée et l'ombre boîte et un article sur la technique que je viens de décrire .

J'espère que ça aide!


1
Encore plus tard pour la fête, mais +1 pour la filterpropriété CSS multiplateforme ... Bien que je ne pense pas que des balises HTML SVG soient nécessaires, tout PNG avec canal alpha fera l'affaire
Guillaume

2
Dudley Storey a raison. Sans le SVG, l'ombre n'apparaît pas dans Firefox. @AntonAL pourrait accepter cette réponse.
javsmo

5
Les filtres DX ne fonctionnent plus sur IE ... Existe-t-il une nouvelle solution pour IE? msdn.microsoft.com/en-us/library/hh801215(v=vs.85).aspx
tb11

2
De nos jours, Firefox prend en charge, filter: drop-shadow(x y blur color); donc l'astuce SVG ne devrait plus être nécessaire.
Raptor007

11
Ne pouvons-nous pas tous convenir que IE aurait dû être jeté à la poubelle il y a des années? Edge est légèrement meilleur, mais Holy Cow M $ avez-vous volontairement remis le développement logiciel à l'ère sombre avec IE? Quelle abomination.
RyanNerd

217

Oui, il est possible d'utiliser filter: dropShadow(x y blur? spread? color?), en CSS ou en ligne:

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);">


8
Pas de support IE ... :(
CF

10
IE devrait comprendre le temps: P
Bryant Jackson

6
-webkit-filter n'est plus nécessaire
Brett Donald

11
2019: qu'est-ce que IE? : P
evilReiko

36

Si vous avez> 100 images pour lesquelles vous souhaitez avoir des ombres portées, je suggère d'utiliser le programme de ligne de commande ImageMagick . Avec cela, vous pouvez appliquer des ombres portées en forme à 100 images en tapant une seule commande! Par exemple:

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

La commande ci-dessus (shell) prend chaque fichier .png dans le répertoire courant, applique une ombre portée et enregistre le résultat dans le répertoire shadow /. Si vous n'aimez pas les ombres portées générées, vous pouvez modifier beaucoup les paramètres; commencez par regarder la documentation pour les ombres , et les instructions générales d' utilisation ont beaucoup d'exemples sympas de choses qui peuvent être faites aux images.

Si vous changez d'avis à l'avenir sur l'apparence des ombres portées - ce n'est qu'une commande pour générer de nouvelles images avec différents paramètres :-)


22
Bien que ce soit une solution, cela ne répond pas à la question!
leo

6
Le demandeur tente de demander au navigateur de rendre l'ombre, et non d'exécuter des scripts sur le serveur qui peuvent créer des ombres. Ce sont des informations utiles mais pas le même espace de problème.
SG1

Quelques notes pour que cela fonctionne: 1. Vous devez créer le répertoire caché avant d'exécuter cette commande (comme avec mkdir shadow) 2. $idevrait être cité (comme dans "$i") ou il s'étouffera si une image a un espace dans son nom de fichier: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. Les fichiers résultants seront nommés filename.png.png. Voici une version entièrement fonctionnelle: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 points - bien que cela soit censé être une illustration de ce qui peut être fait, plutôt qu'un programme pleinement fonctionnel! J'ai corrigé le suffixe double .png et les guillemets; la chose d'annuaire que je pense ne ferait
qu'empêcher

35
img {
  -webkit-filter: drop-shadow(5px 5px 5px #222222);
  filter: drop-shadow(5px 5px 5px #222222);
}

Cela a très bien fonctionné pour moi. Une chose à noter dans IE, vous avez besoin de la couleur (# 222222) trois caractères ne fonctionnent pas.


29

Comme Dudley l'a mentionné dans sa réponse, cela est possible avec le filtre CSS ombre portée pour webkit, SVG pour Firefox et les filtres DirectX pour Internet Explorer 9-.

Une étape supplémentaire consiste à intégrer le SVG, en éliminant la demande supplémentaire:

.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')";
}

1
Cela fonctionne bien .. mieux que si je définissais le SVG à l'intérieur des balises HTML. (Firefox)
Oki Erie Rinaldi

18

Ajoutez une bordure avec un rayon dans votre classe si c'est un bloc. car par défaut, l'ombre s'applique sur la bordure du bloc, même si votre image a un coin arrondi.

border-radius: 4px;

changer son rayon de bordure en fonction de votre coin d'image. J'espère que cette aide.


12

Ajoutez simplement ceci:

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

exemple:

<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); 
}


3

Quand j'ai posté cela à l'origine, ce n'était pas possible, c'est donc la solution de contournement. Maintenant, je suggère simplement d'utiliser d'autres réponses.

Il n'y a aucun moyen d'obtenir exactement le contour de l'image, mais vous pouvez le simuler avec un div derrière l'image au centre.

Si mon astuce ne fonctionne pas, vous devez découper l'image et le faire pour chacune des petites images. (plus il y a d'images, plus l'ombre sera précise), mais pour la plupart des images, elle semble correcte avec une seule img.

ce que vous devez faire est de mettre un div enveloppant autour de votre img comme si

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

puis vous mettez un séparateur vide à l'intérieur de l'enveloppe (cela servira d'ombre)

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

puis vous devez faire apparaître l'ombre derrière l'img avec 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;
}

maintenant positionnez l'imgWrap pour positionner l'img d'origine ... pour centrer l'ombre de l'img vous pouvez jouer avec les deux premières valeurs de l'ombre de boîte les rendant négatives .... ou vous pouvez positionner l'img et les diviseurs d'ombre absolument faire des valeurs img top et left = 0 et les valeurs shadow div = la moitié de la largeur et de la hauteur img respectivement.

Si cela semble horrible, coupez votre image et réessayez.

(Si vous ne voulez pas que l'ombre derrière l'image soit juste sur le contour, vous devez rendre votre image opaque et la faire agir comme si elle était transparente, ce qui n'est pas si difficile et vous pouvez commenter et je vous expliquerai plus tard)


quand j'ai répondu que ce n'était pas possible, je suppose que c'est maintenant. L'avenir est là!
Xitcod13

2

Dans mon cas, il devait fonctionner sur des navigateurs mobiles modernes, avec une image PNG de différentes formes et transparence. J'ai créé une ombre portée à l'aide d'un double de l'image. Cela signifie que j'ai deux imgéléments de la même image, l'un au-dessus de l'autre (en utilisant position: absolute), et celui derrière a les règles suivantes qui lui sont appliquées:

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

Cela inclut un filtre de luminosité afin d'assombrir l'image du bas, et un filtre de flou afin de projeter l'ombre portée avec un effet flou. Une opacité à 50% est ensuite appliquée afin de l'assouplir.

Cela peut être appliqué à travers le navigateur à l'aide des indicateurs mozet ms.

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



1

Ce ne sera pas possible avec css - une image est un carré, et donc l'ombre serait l'ombre d'un carré. La façon la plus simple serait d'utiliser Photoshop / Gimp ou tout autre éditeur d'image pour appliquer l'ombre comme le dessin de base.


Merci pour votre réponse. Mais, ajouter une image dans l'éditeur aura des problèmes à l'avenir, quand j'aurai> 100 images et que je devrais modifier légèrement les ombres. La meilleure solution à mon problème consiste à ajouter une image d'ombre supplémentaire sous chaque image en question avec jQuery.
AntonAL

1

Une astuce que j'utilise souvent lorsque j'ai juste besoin d'une "petite" ombre (lire: le contour ne doit pas être super précis) consiste à placer un DIV avec un remplissage radial de 100% - noir à 100% - transparent sous l'image. Le CSS pour le DIV ressemble à quelque chose comme:

.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 */
  }

Cela créera un `` point '' noir circulaire délavé sur un DIV 320x320. Si vous modifiez la hauteur ou la largeur du DIV, vous obtenez un ovale correspondant. Très agréable à créer, par exemple, des ombres sous des bouteilles ou d'autres formes cylindriques.

Il existe un outil absolument incroyable et super excellent pour créer des dégradés CSS ici:

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

ps: Faites un clic de publicité de courtoisie lorsque vous l'utilisez. (Et, non, je n'y suis pas affilié. Mais les clics de courtoisie devraient devenir un peu une habitude, en particulier pour les outils que vous utilisez souvent ... dites simplement ... puisque nous travaillons tous sur le net ... )


J'ai pu voir cela très joli quand il a été modifié un peu
BeachInCalifornia.com

1
"Clic sur l'annonce avec courtoisie"? Sérieusement, comment arnaquer les annonceurs est-il une bonne chose pour le Net? Beaucoup d'entre nous sont des annonceurs nous-mêmes, ou sont payés par eux, donc déclencher des frais pour les annonceurs pour des publicités pour des produits que vous n'achèterez jamais est une chose vraiment désagréable à faire. Si vous êtes intéressé par une annonce, cliquez dessus par tous les moyens, mais ne faites pas ça!
alastair

Oh, sortez de vos hauteurs morales, Alastair. Le monde réel semble un peu différent. "Arnaquer les annonceurs"? Vraiment? LOL - Donnez-moi une pause, l'homme. Je travaille dans la publicité et le marketing depuis près de 30 ans. Pour placer l'étrange courtoisie, le clic n'a aucune influence que celle de soutenir GRATUITEMENT les sites que vous utilisez. Si vous vous inquiétez de l'inflation des prix, etc., craignez les tendances de plus en plus monopolistiques dans l'industrie. C'est ce qui fausse les prix publicitaires, pas le cliquetis de courtoisie.
Rid Iculous

Cela a l'air horrible sur FF et IE
barrypicker

1

Vous ne pouvez pas le faire de manière fiable sur tous les navigateurs. Microsoft ne prend plus en charge les filtres DX à partir d'IE10 +, donc aucune des solutions ici ne fonctionne pleinement:

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

La seule propriété qui fonctionne de manière fiable sur tous les navigateurs est box-shadow, et cela place simplement la bordure sur votre élément (par exemple, un div), résultant en une bordure carrée:

shadow-box: horizontalOffset verticalOffset blurDistance spreadDistance encart de couleur ;

par exemple

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

Si vous avez une image «carrée» mais avec des coins arrondis uniformes, l'ombre portée fonctionne avec border-radius, vous pouvez donc toujours émuler les coins arrondis de votre image dans votre div.

Voici la documentation Microsoft pour box-shadow:

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


J'apprécie la réponse simple. Aucun des exemples ci-dessus ne fonctionne pour moi.
barrypicker

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.