Тень для изображения PNG в CSS - PullRequest
175 голосов
/ 06 июля 2010

У меня есть изображение 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;

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

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

Ответы [ 15 ]

240 голосов
/ 16 октября 2012

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

Некоторые сравнения истинных теней и теней и статьи о технике, которую я только что описал .

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

154 голосов
/ 17 апреля 2014

Да, возможно использовать filter: dropShadow(x y blur? spread? color?), либо в CSS, либо в строке:

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);">
37 голосов
/ 06 июля 2010

Если у вас есть> 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 /. Если вам не нравятся сгенерированные тени, вы можете значительно изменить параметры; Начните с просмотра документации по теням , а общие инструкции по использованию содержат множество интересных примеров того, что можно сделать с изображениями.

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

28 голосов
/ 12 января 2014

Как Дадли упомянул в своем ответе , это возможно с помощью CSS-фильтра с отбрасываемой тенью для 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')";
}
19 голосов
/ 22 августа 2017
img {
  -webkit-filter: drop-shadow(5px 5px 5px #222222);
  filter: drop-shadow(5px 5px 5px #222222);
}

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

17 голосов
/ 05 июля 2011

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

border-radius: 4px;

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

10 голосов
/ 09 апреля 2014

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

-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); 
}
5 голосов
/ 16 декабря 2015

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

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

-webkit-filter: drop-shadow(0px 0px 0px rgba(255,255,255,0.80));
2 голосов
/ 09 марта 2015

В моем случае это должно было работать в современных мобильных браузерах с 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/

2 голосов
/ 14 мая 2012

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

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

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

вам нужно сделать обтекание 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 = 0, а теневые div-значения равны половине ширины и высоты img соответственно.

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

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

...