Cień dla obrazu PNG w CSS

210

Mam obraz PNG, który ma dowolny kształt (nie kwadratowy).

Muszę zastosować efekt cienia do tego obrazu.

Standardowe podejście ...

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

... wyświetla cienie dla tego obrazu, jakby był kwadratem. Widzę więc mój obraz i kwadratowy cień, który nie jest zgodny z formą obiektu, wyświetlany na obrazie.

Czy jest jakiś sposób, aby zrobić to poprawnie?

AntonAL
źródło

Odpowiedzi:

261

Trochę za późno na imprezę, ale tak, jest całkowicie możliwe tworzenie „prawdziwych” dynamicznych cieni wokół PNG w maskach alfa, przy użyciu kombinacji filtrów dropshadow (dla Webkit), SVG (dla Firefox) i filtrów DX dla 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>

Kilka porównań między prawdziwym cieniem i cieniem i artykułem na temat techniki, którą właśnie opisałem .

Mam nadzieję, że to pomoże!

Dudley Storey
źródło
1
Jeszcze bardziej późno na imprezę, ale +1 dla filterwłaściwości CSS wielopłytkowej ... Chociaż nie sądzę, żeby tagi SVG HTML były potrzebne, jakikolwiek PNG z kanałem alfa
załatwi sprawę
2
Dudley Storey ma rację. Bez SVG cień nie pojawia się w przeglądarce Firefox. @AntonAL może zaakceptować tę odpowiedź.
javsmo
5
Filtry DX już nie działają w IE ... Czy jest jakieś nowe rozwiązanie dla IE? msdn.microsoft.com/en-us/library/hh801215(v=vs.85).aspx
tb11
2
Obecnie Firefox obsługuje, filter: drop-shadow(x y blur color); więc sztuczka SVG nie powinna już być konieczna.
Raptor007,
11
Czy nie wszyscy możemy po prostu zgodzić się, że IE powinien był zostać wyrzucony na śmietnik lata temu? Edge jest nieco lepszy, ale Święta krowa M $ celowo przywróciłeś programowanie do ciemności dzięki IE? Co za obrzydliwość.
RyanNerd
216

Tak, można to zrobić za pomocą filter: dropShadow(x y blur? spread? color?)CSS lub wbudowanego:

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
źródło
8
Brak obsługi IE ... :(
CF
10
IE powinien nadążyć za czasem: P
Bryant Jackson
6
-webkit-filter nie jest już potrzebny
Brett Donald
11
2019: co to jest IE? : P
evilReiko
36

Jeśli masz> 100 obrazów, dla których chcesz mieć cienie, sugerowałbym użycie programu wiersza poleceń ImageMagick . Dzięki temu możesz zastosować cienie w kształcie do 100 zdjęć, wpisując jedno polecenie! Na przykład:

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

Powyższe polecenie (powłoki) pobiera każdy plik .png z bieżącego katalogu, stosuje cień i zapisuje wynik w katalogu shadow /. Jeśli nie podoba Ci się generowany cień, możesz bardzo poprawić parametry; zacznij od przejrzenia dokumentacji cieni i ogólnych instrukcji użytkowania zawierają wiele fajnych przykładów rzeczy, które można zrobić z obrazami.

Jeśli w przyszłości zmienisz zdanie na temat wyglądu cieni - to tylko jedno polecenie, aby wygenerować nowe obrazy o różnych parametrach :-)

psmears
źródło
22
Chociaż jest to rozwiązanie, nie odpowiada na pytanie!
leo
6
Pytający próbuje zmusić przeglądarkę do renderowania cienia, a nie do uruchamiania skryptów na serwerze, które mogą tworzyć cienie. Jest to użyteczna informacja, ale nie ta sama przestrzeń problemu.
SG1,
Kilka uwag, aby to zadziałało: 1. Musisz utworzyć katalog cienia przed uruchomieniem tego polecenia (np. Z mkdir shadow) 2. $ipowinieneś zacytować (jak w "$i") lub zadławi się, jeśli w nazwie pliku będzie spacja: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. Pliki wynikowe zostaną nazwane filename.png.png. Oto w pełni działająca wersja: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: Dobre punkty - choć należy pamiętać, że ma to być ilustracja tego, co można zrobić, a nie w pełni działający program! Naprawiłem podwójny sufiks .png i cytaty; coś, co wydaje mi się przeszkadzać ...
psmears
34
img {
  -webkit-filter: drop-shadow(5px 5px 5px #222222);
  filter: drop-shadow(5px 5px 5px #222222);
}

To działało dla mnie świetnie. Należy zauważyć, że w IE potrzebujesz pełnego koloru (# 222222), trzy znaki nie działają.

Jaclyn U
źródło
29

Jak wspomniał Dudley w swojej odpowiedzi jest to możliwe dzięki filtrowi CSS typu drop-shadow dla webkita, SVG dla Firefoxa i filtrom DirectX dla Internet Explorera 9-.

Kolejnym krokiem jest wprowadzenie SVG, eliminując dodatkowe żądanie:

.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
źródło
1
Działa dobrze .. lepiej niż gdybym zdefiniował SVG wewnątrz tagów HTML. (firefox)
Oki Erie Rinaldi
18

Dodaj ramkę z promieniem w swojej klasie, jeśli jest to blok. ponieważ domyślnie cień będzie stosowany na granicy bloku, nawet jeśli obraz ma zaokrąglony narożnik.

border-radius: 4px;

zmień jego promień obramowania zgodnie ze swoim narożnikiem obrazu. Mam nadzieję, że to pomoże.

anupal
źródło
12

Po prostu dodaj to:

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

przykład:

<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
źródło
6

Oto gotowy fragment kodu animacji po najechaniu blaskiem:

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

-webkit-filter: drop-shadow(0px 0px 0px rgba(255,255,255,0.80));
Dmitrij Kaigorodov
źródło
inne niż webkit?
mmm
3

Kiedy zamieściłem to pierwotnie, nie było to możliwe, więc jest to obejście. Teraz po prostu sugeruję użycie innych odpowiedzi.

Nie ma sposobu, aby uzyskać dokładny kontur obrazu, ale można go sfałszować za pomocą div za obrazem pośrodku.

Jeśli moja sztuczka nie działa, musisz wyciąć obraz i zrobić to dla każdego z małych obrazów. (im więcej zdjęć, tym dokładniejszy będzie wyglądać cień), ale w przypadku większości zdjęć wygląda dobrze z jednym zdjęciem.

co musisz zrobić, to tak otoczyć img div

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

następnie wsuwasz pustą przegrodę do owinięcia (będzie to cień)

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

a następnie musisz sprawić, by cień pojawił się za obrazkiem za pomocą 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;
}

umieść teraz imgWrap, aby ustawić oryginalny obraz ... w celu wyśrodkowania cienia obrazu, możesz pomieszać z pierwszymi dwoma wartościami cienia-pudełka, czyniąc je ujemnymi .... lub możesz ustawić obraz i obraz cienia całkowicie czyniąc img górną i lewą wartość = 0, a wartości div cienia = połowę odpowiednio szerokości i wysokości img.

Jeśli to wygląda okropnie, wytnij obraz i spróbuj ponownie.

(Jeśli nie chcesz, aby cień za imgiem znajdował się tylko na konturze, musisz sprawić, by twój img był nieprzezroczysty i sprawić, by działał tak, jakby był przezroczysty, co nie jest takie trudne i możesz to skomentować, a wyjaśnię później)

Xitcod13
źródło
kiedy odpowiedziałem, nie było to możliwe, chyba tak jest. Przyszłość jest tutaj!
Xitcod13
2

W moim przypadku musiał działać na nowoczesnych przeglądarkach mobilnych, z obrazem PNG w różnych kształtach i przezroczystości. Cień utworzyłem przy użyciu duplikatu obrazu. Oznacza to, że mam dwa imgelementy tego samego obrazu, jeden na drugim (za pomocą position: absolute), a jeden za nim ma następujące zasady:

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

Obejmuje to filtr jasności w celu przyciemnienia dolnego obrazu oraz filtr rozmycia w celu rzucenia efektu rozmazania efektu cienia. Następnie stosuje się krycie w 50%, aby go zmiękczyć.

Można to zastosować w różnych przeglądarkach za pomocą mozims flag .

Przykład: https://jsfiddle.net/5mLssm7o/

ja robię
źródło
1

Nie będzie to możliwe z css - obraz jest kwadratem, więc cień byłby cieniem kwadratu. Najłatwiejszym sposobem byłoby użycie programu Photoshop / Gimp lub dowolnego innego edytora obrazów w celu zastosowania cienia jak rysowanie rdzenia.

oezi
źródło
Dzięki za odpowiedź. Ale dodanie obrazu w edytorze będzie miało problemy w przyszłości, kiedy będę miał> 100 obrazów i powinienem trochę ulepszyć cienie. Najlepszym rozwiązaniem mojego problemu - jest dodanie dodatkowego obrazu cienia pod każdym obrazem za pomocą jQuery.
AntonAL,
1

Sztuczka, której często używam, gdy potrzebuję tylko „małego” cienia (czytaj: kontur nie może być super precyzyjny), polega na umieszczeniu DIV z wypełnieniem promieniowym 100% -czarno-100% -przezroczystym pod obrazem. CSS dla DIV wygląda mniej więcej tak:

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

Spowoduje to utworzenie okrągłej czarnej, wyblakłej „kropki” na DIV 320 x 320. Jeśli przeskalujesz wysokość lub szerokość DIV, otrzymasz odpowiedni owal. Bardzo miło jest tworzyć np. Cienie pod butelkami lub inne kształty w kształcie walca.

Istnieje absolutnie niesamowite, super doskonałe narzędzie do tworzenia gradientów CSS:

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

ps: Wykonaj uprzejme kliknięcie reklamy, gdy z niej korzystasz. (I nie, nie jestem z tym związany. Ale uprzejme klikanie powinno stać się trochę nawykiem, szczególnie w przypadku narzędzia, którego często używasz ... po prostu mówię ... ponieważ wszyscy pracujemy w sieci ... )

Śmieszny
źródło
Widziałem to całkiem ładnie, gdy nieco zmodyfikowałem
BeachInCalifornia.com
1
„Uprzejme kliknięcie reklamy”? Poważnie, w jaki sposób oszukanie reklamodawców jest dobre dla sieci? Wielu z nas jest reklamodawcami sami lub są przez nich opłacani, więc naliczanie opłat dla reklamodawców za reklamy produktów, których nigdy nie kupisz, jest naprawdę nieprzyjemne. Jeśli jesteś zainteresowany reklamą, kliknij ją na wszelki wypadek, ale nie rób tego!
alastair
Och, zejdź z moralnego wzniesienia, Alastair. Świat rzeczywisty wygląda nieco inaczej. „Zdzierać reklamodawców”? Naprawdę? LOL - Daj spokój, stary. Zajmuję się reklamą i marketingiem od prawie 30 lat. Aby umieścić dziwne kliknięcie grzecznościowe, nie ma żadnego wpływu poza obsługą stron, z których korzystasz ZA DARMO. Jeśli martwisz się inflacją nagród itp., Martw się coraz bardziej monopolizującymi trendami w branży. To zniekształcają nagrody reklamowe, a nie dziwne kliknięcie grzecznościowe.
Rid Iculous
To wygląda okropnie na FF i IE
barrypicker,
1

Nie można tego zrobić niezawodnie we wszystkich przeglądarkach. Microsoft nie obsługuje już filtrów DX od IE10 +, więc żadne z rozwiązań tutaj nie działa w pełni:

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

Jedyną właściwością, która działa niezawodnie we wszystkich przeglądarkach, jest box-shadowustawienie ramki na elemencie (np. Div), co daje kwadratową ramkę:

box-shadow: horizontalOffset verticalOffset blur Rozmycie odległości Odstęp koloru wstawki;

na przykład

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

Jeśli zdarzy się, że masz obraz „kwadratowy”, ale z jednolitymi zaokrąglonymi narożnikami, cień z nim współpracuje border-radius, więc zawsze możesz emulować zaokrąglone rogi obrazu w div.

Oto dokumentacja Microsoft dla box-shadow:

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

Chris Halcrow
źródło
Doceniam bezpośrednią odpowiedź. Żaden z powyższych przykładów nie działa dla mnie.
barrypicker