web-dev-qa-db-fra.com

Ombre portée pour l'image PNG en CSS

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 s'il s'agissait d'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.

Est-il possible de le faire correctement?

179
AntonAL

Un peu tard pour le parti, mais oui, il est tout à fait possible de créer de "vraies" ombres portées dynamiques autour des PNG masqués en alpha, en combinant les 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 les vraies ombres portées et les ombres boîte et n article sur la technique que je viens de décrire .

J'espère que ça aide!

244
Dudley Storey

Oui, il est possible d'utiliser filter: dropShadow(x y blur? spread? color?) , soit en CSS, soit 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);">
163
Abdul

Si vous voulez plus de 100 images pour lesquelles vous souhaitez créer des ombres portées, je vous suggère d'utiliser le programme en ligne de commande ImageMagick . Avec cela, vous pouvez appliquer des ombres portées en forme à 100 images simplement en tapant une 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 actuel, 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 considérablement les paramètres. Commencez par regarder documentation sur les ombres , et le général instructions d'utilisation contient de nombreux exemples intéressants de choses pouvant être effectuées sur les images.

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

37
psmears

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

Une étape supplémentaire consiste à intégrer le SVG, en éliminant la requête 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')";
}
28
Karl Horky
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, c'est-à-dire que vous avez besoin de la couleur (# 222222), trois caractères ne fonctionnent pas.

19
Jaclyn U

Ajoutez une bordure de rayon dans votre classe si c'est un bloc. car par défaut, l'ombre s'appliquera sur la bordure du bloc, même si votre image a des coins arrondis.

border-radius: 4px;

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

17
anupal

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); 
}
10
Mahmoud Zalt

Voici l'extrait de code d'animation prêt pour le survol:

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

-webkit-filter: drop-shadow(0px 0px 0px rgba(255,255,255,0.80));
5
Dmitry Kaigorodov

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

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

Cela inclut un filtre de luminosité pour assombrir l’image du bas et un filtre de flou pour projeter l’effet de tache que l’ombre portée a habituellement. Une opacité à 50% est ensuite appliquée afin de la ramollir.

Ceci peut être appliqué à tous les navigateurs en utilisant les indicateurs moz et ms.

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

2
ido

Quand j'ai posté ceci à 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’existe aucun moyen d’obtenir le contour de l’image exactement 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 la faire pour chacune des petites images. (plus il y a d'images, plus l'ombre sera précise), mais pour la plupart des images, l'apparence est correcte avec une seule image.

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

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

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

et ensuite 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;
}

positionnez maintenant imgWrap pour positionner l'original img ... pour centrer l'ombre de l'img, vous pouvez jouer avec les deux premières valeurs de la case-shadow en les rendant négatives .... ou vous pouvez positionner img et les séparations d'ombre de manière absolue rendant img top et left valeurs = 0 et les valeurs ombre div = moitié de la largeur et de la hauteur de img, respectivement.

Si cela vous semble horrible, coupez court et essayez à nouveau.

(Si vous ne voulez pas que l'ombre se cache derrière l'image 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 l'expliquerai plus tard.)

2
Xitcod13

Peut-être que vous êtes à la recherche de cela. http://lineandpixel.com/blog/png-shadow

img { png-shadow: 5px 5px 5px #222; }
1
Abhishek D

Cela ne sera pas possible avec css - une image est un carré, et donc l'ombre serait l'ombre d'un carré. Le moyen le plus simple consiste à utiliser photoshop/gimp ou tout autre éditeur d’images pour appliquer l’ombre au dessin de base.

1
oezi

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 +. Par conséquent, aucune des solutions proposées 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 met simplement la bordure sur votre élément (par exemple, un div), ce qui donne une bordure carrée:

box-shadow: horizontalOffset verticalOffset blurDistance spreadDistance couleur incrusté;

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, de sorte que vous pouvez toujours imiter les coins arrondis de votre image dans votre div.

Voici la documentation de Microsoft pour box-shadow:

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

1
Chris Halcrow

Vous pouvez utiliser une fonctionnalité proposée pour les ombres portées de forme arbitraire. Vous pouvez le voir ici, avec la permission de Lea Verou:

http://www.netmagazine.com/features/hot-web-standards-css-blending-modes-and-filters-shadow-dom

La prise en charge du navigateur est minime, cependant.

1
avramov

Un truc que j’utilise souvent quand j’ai juste besoin "d’un peu" d’ombre (lire: les contours ne doivent pas être super précis), c’est de placer un DIV avec un remplissage radial 100% noir à 100% transparent sous l’image. Le CSS pour la 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" fondu noir circulaire sur un DIV 320x320. Si vous redimensionnez la hauteur ou la largeur de la DIV, vous obtenez un ovale correspondant. Très agréable à créer par exemple des ombres sous des bouteilles ou d'autres formes en forme de cylindre.

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

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

ps: Faites une annonce de courtoisie lorsque vous l'utilisez. (Et, non, je n'y suis pas affilié. Mais cliquer sur la courtoisie devrait devenir une habitude, surtout pour les outils que vous utilisez souvent ... dites simplement ... puisque nous travaillons tous sur le net ... )

1
Rid Iculous