Тень для изображения PNG в CSS

211

У меня есть изображение PNG, которое имеет свободную форму (не квадрат).

Мне нужно применить эффект тени к этому изображению.

Стандартный подход ...

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

... отображает тени для этого изображения, как будто это квадрат. Итак, я вижу свое изображение и квадратную тень, которая не соответствует форме объекта, отображаемого на изображении.

Есть ли способ сделать это правильно?

AntonAL
источник

Ответы:

261

Немного опоздал на вечеринку, но да, вполне возможно создать «настоящие» динамические тени вокруг PNG с альфа-маской, используя комбинацию drophadow-filter (для Webkit), SVG (для Firefox) и DX-фильтров для 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>

Некоторые сравнения между настоящими drop-shadow и box-shadow и статьей о технике, которую я только что описал .

Надеюсь, это поможет!

Дадли Стори
источник
1
Еще более поздно для вечеринки, но +1 для CSS- filterсвойства кроссплатформенности ... Хотя я не думаю, что нужны HTML-теги SVG, любой PNG с альфа-каналом справится с задачей
Гийом
2
Дадли Стори прав. Без SVG тень не появляется в Firefox. @AntonAL может принять этот ответ.
Javsmo
5
Фильтры DX больше не работают в IE ... Есть ли новое решение для IE? msdn.microsoft.com/en-us/library/hh801215(v=vs.85).aspx
tb11
2
В наши дни Firefox поддерживает, filter: drop-shadow(x y blur color); поэтому трюк SVG больше не нужен.
Raptor007
11
Разве мы не все можем согласиться с тем, что IE нужно было выбросить в кучу мусора много лет назад? Edge немного лучше, но святая корова M $, вы целенаправленно вернули разработку программного обеспечения в темное время с помощью IE? Какая мерзость.
RyanNerd
217

Да, это возможно с помощью filter: dropShadow(x y blur? spread? color?)CSS или inline:

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
Нет поддержки IE ... :(
CF
10
IE должен идти в ногу со временем: P
Брайант Джексон
6
-webkit-filter больше не нужен
Бретт Дональд
11
2019: что такое IE? : P
evilReiko
36

Если у вас есть> 100 изображений, для которых вы хотите иметь тени, я бы предложил использовать программу командной строки ImageMagick . При этом вы можете применить фасонные тени на 100 изображений, просто набрав одну команду! Например:

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

Приведенная выше команда (shell) берет каждый файл .png в текущем каталоге, применяет тень и сохраняет результат в каталоге shadow /. Если вам не нравятся сгенерированные тени, вы можете настроить параметры; Начните с просмотра документации по теням , и в общих инструкциях по использованию есть много интересных примеров того, что можно сделать с изображениями.

Если в будущем вы передумаете над видом теней - это всего лишь одна команда для создания новых изображений с различными параметрами :-)

psmears
источник
22
Хотя это решение, оно не отвечает на вопрос!
Лев
6
Запрашивающий пытается заставить браузер отображать тень, а не выполнять сценарии на сервере, которые могут создавать тени. Это полезная информация, но не та же самая проблемная область.
SG1
Пара замечаний, чтобы заставить это работать: 1. Вам нужно создать теневой каталог перед выполнением этой команды (например, с помощью mkdir shadow) 2. $iследует заключить в кавычки (как в "$i"), иначе он захлебнется, если в имени файла есть пробел:for i in *.png; do convert "$i" '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage shadow/"$i".png; done
Эндрю Мачерет
2
3. Полученные файлы будут названы filename.png.png. Вот полностью рабочая версия:for i in *.png; do convert "$i" '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage shadow/"$i"; done
Эндрю Мачерет
@AndrewMacheret: Хорошие моменты - хотя обратите внимание, это предназначено для иллюстрации того, что можно сделать, а не для полностью работающей программы! Я исправил двойной суффикс .png и кавычки; каталог, который я чувствую, просто
мешает
35
img {
  -webkit-filter: drop-shadow(5px 5px 5px #222222);
  filter: drop-shadow(5px 5px 5px #222222);
}

Это отлично сработало для меня. Стоит отметить, что в IE вам нужен полноцветный (# 222222) три символа, которые не работают.

Жаклин У
источник
29

Как Дадли упомянул в своем ответе это возможно с помощью CSS-фильтра drop-shadow для webkit, SVG для Firefox и DirectX для Internet Explorer 9-.

Еще один шаг - встроить SVG, исключив дополнительный запрос:

.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
Это работает хорошо ... лучше, чем если бы я определял SVG внутри тегов HTML. (Firefox)
Оки Эри Ринальди
18

Добавьте границу с радиусом в своем классе, если это блок. потому что по умолчанию тень будет применяться на границе блока, даже если ваше изображение имеет закругленный угол.

border-radius: 4px;

измените радиус границы в соответствии с вашим углом изображения. Надеюсь, это поможет.

anupal
источник
12

Просто добавьте это:

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

пример:

<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); 
}
Махмуд Зальт
источник
6

Вот готовый фрагмент кода анимации свечения для этого:

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

-webkit-filter: drop-shadow(0px 0px 0px rgba(255,255,255,0.80));
Дмитрий Кайгородов
источник
кроме вебкита?
ммм
3

Когда я разместил это изначально, это было невозможно, так что это обходной путь. Теперь я просто предлагаю использовать другие ответы.

Невозможно точно получить контур изображения, но вы можете подделать его с помощью div за изображением в центре.

Если мой трюк не сработает, вы должны разрезать изображение и сделать это для каждого из маленьких изображений. (чем больше изображений, тем точнее будет выглядеть тень), но для большинства изображений она выглядит хорошо только с одним изображением.

что вам нужно сделать, это положить обернуть div вокруг вашего img, как это так

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

затем вы помещаете пустой разделитель внутри обертки (это будет служить тенью)

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

и затем вам нужно сделать так, чтобы тень появлялась за img с помощью 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;
}

Теперь поместите imgWrap, чтобы расположить оригинал img ..., чтобы центрировать тень img, которую вы можете связать с первыми двумя значениями box-shadow, делая их отрицательными .... или вы можете позиционировать img и div div тени полностью делая значения img top и left = 0, а значения shadow div = половину ширины и высоты img соответственно.

Если это выглядит ужасно, порежьте ваше изображение и попробуйте снова.

(Если вы не хотите, чтобы тень от img находилась только на контуре, вам нужно сделать img непрозрачным и заставить его работать так, как если бы он был прозрачным, что не так сложно, и вы можете прокомментировать, а я объясню позже)

Xitcod13
источник
когда я ответил, что это невозможно, я думаю, что теперь это так. Будущее уже здесь!
Xitcod13
2

В моем случае это должно было работать в современных мобильных браузерах с PNG-изображением различной формы и прозрачности. Я создал тень, используя дубликат изображения. Это означает, что у меня есть два imgэлемента одного и того же изображения, один поверх другого (использующий position: absolute), а к одному позади применяются следующие правила:

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

Это включает в себя фильтр яркости, чтобы затемнить нижнее изображение, и фильтр размытия, чтобы создать эффект размытой тени. Непрозрачность в 50% тогда применена, чтобы смягчить это.

Это может быть применено кросс-браузер с использованием mozиms флаги.

Пример: https://jsfiddle.net/5mLssm7o/

я делаю
источник
1

Это не будет возможно с css - изображение является квадратом, и поэтому тень будет тенью квадрата. Самый простой способ - использовать Photoshop / GIMP или любой другой графический редактор для применения тени, как при отрисовке ядра.

oezi
источник
Спасибо за ответ. Но добавление изображения в редакторе будет иметь проблемы в будущем, когда у меня будет> 100 изображений и я должен немного подправить тени. Лучшее решение моей проблемы - добавить дополнительные тени под каждым изображением с помощью jQuery.
AntonAL
1

Уловка, которую я часто использую, когда мне просто нужна «небольшая» тень (читай: контур не должен быть сверхточным), помещает DIV с радиальной заливкой от 100% черного до 100% прозрачного изображения. CSS для DIV выглядит примерно так:

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

Это создаст круглую черную блеклую «точку» на DIV 320x320. Если вы масштабируете высоту или ширину DIV, вы получите соответствующий овал. Очень приятно создавать, например, тени под бутылками или другие цилиндрические формы.

Здесь есть абсолютно невероятный, супер-отличный инструмент для создания CSS-градиентов:

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

PS: Сделайте вежливый рекламный клик, когда вы его используете. (И нет, я не связан с этим. Но вежливое нажатие должно стать привычкой, особенно для инструмента, который вы часто используете ... просто говорю ... так как мы все работаем в сети ... )

Смешной
источник
Я мог видеть, что это выглядит довольно хорошо, когда немного
изменился
1
«Предоставлено рекламным кликом»? Серьезно, как похищение рекламодателей полезно для сети? Многие из нас сами являются рекламодателями или им платят, поэтому инициирование платежей для рекламодателей за рекламу товаров, которые вы никогда не собираетесь покупать, - это действительно неприятная вещь. Если вы заинтересованы в объявлении, нажмите на него во что бы то ни стало, но не делайте этого!
Аластер
Ой, отойди от своего морального превосходства, Аластер. Реальный мир выглядит немного иначе. "Срывать рекламодателей"? В самом деле? LOL - Дай мне перерыв, чувак. Я занимаюсь рекламой и маркетингом почти 30 лет. Размещение нечетного клика вежливости не имеет никакого влияния, кроме поддержки сайтов, которые вы используете БЕСПЛАТНО. Если вас беспокоит инфляция призов и т. Д., Беспокойтесь о все более монополизирующихся тенденциях во всей отрасли. Вот что искажает рекламные призы, а не странный клик вежливости.
Rid Iculous
Это выглядит ужасно на FF и IE
barrypicker
1

Вы не можете сделать это надежно во всех браузерах. Microsoft больше не поддерживает фильтры DX начиная с IE10 +, поэтому ни одно из решений здесь не работает полностью:

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

Единственное свойство, которое надежно работает во всех браузерах box-shadow , и это просто ставит границу вашего элемента (например, div), в результате чего получается квадратная граница:

box-shadow: горизонтальныйOffset вертикальныйOffset blurDistance diffDistance color ;

например

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

Если у вас получилось изображение «квадратное», но с равномерными закругленными углами, тень будет работать с border-radius , так что вы всегда сможете эмулировать закругленные углы своего изображения в своем div.

Вот документация Microsoft для box-shadow:

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

Крис Хэлкроу
источник
Я ценю прямой ответ. Ни один из приведенных выше примеров не работает для меня.
barrypicker