Change color of PNG image via CSS?

2018-12-31 17:00发布

Given a transparent PNG displaying a simple shape in white, is it possible to somehow change the color of this through CSS? Some kind of overlay or what not?

14条回答
皆成旧梦
2楼-- · 2018-12-31 17:43

The simplest one line that worked for me:

filter: opacity(0.5) drop-shadow(0 0 0 blue);

You can adjust opacity from 0 to 1 to make color lighter or darker.

查看更多
孤独总比滥情好
3楼-- · 2018-12-31 17:44

The img tag has a background property just like any other. If you have a white PNG with a transparent shape, like a stencil, then you can do this:

<img src= 'stencil.png' style= 'background-color: red'>
查看更多
忆尘夕之涩
4楼-- · 2018-12-31 17:48

I've been able to do this using SVG filter. You can write a filter that multiplies the color of source image with the color you want to change to. In the code snippet below, flood-color is the color we want to change image color to (which is Red in this case.) feComposite tells the filter how we're processing the color. The formula for feComposite with arithmetic is (k1*i1*i2 + k2*i1 + k3*i2 + k4) where i1 and i2 are input colors for in/in2 accordingly. So specifying only k1=1 means it will do just i1*i2, which means multiplying both input colors together.

Note: This only works with HTML5 since this is using inline SVG. But I think you might be able to make this work with older browser by putting SVG in a separate file. I haven't tried that approach yet.

Here's the snippet:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="60" height="90" style="float:left">
  <defs>
    <filter id="colorMask1">
      <feFlood flood-color="#ff0000" result="flood" />
      <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
    </filter>
  </defs>
  <image width="100%" height="100%" xlink:href="http://i.stack.imgur.com/OyP0g.jpg" filter="url(#colorMask1)" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="60" height="90" style="float:left">
  <defs>
    <filter id="colorMask2">
      <feFlood flood-color="#00ff00" result="flood" />
      <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
    </filter>
  </defs>
  <image width="100%" height="100%" xlink:href="http://i.stack.imgur.com/OyP0g.jpg" filter="url(#colorMask2)" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="60" height="90" style="float:left">
  <defs>
    <filter id="colorMask3">
      <feFlood flood-color="#0000ff" result="flood" />
      <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
    </filter>
  </defs>
  <image width="100%" height="100%" xlink:href="http://i.stack.imgur.com/OyP0g.jpg" filter="url(#colorMask3)" />
</svg>

查看更多
低头抚发
5楼-- · 2018-12-31 17:53

I required a specific colour, so filter didn't work for me.

Instead, I created a div, exploiting CSS multiple background images and the linear-gradient function (which creates an image itself). If you use the overlay blend mode, your actual image will be blended with the generated "gradient" image containing your desired colour (here, #BADA55)

.colored-image {
        background-image: linear-gradient(to right, #BADA55, #BADA55), url("https://i.imgur.com/lYXT8R6.png");
        background-blend-mode: overlay;
        background-size: contain;
        width: 200px;
        height: 200px;        
    }
<div class="colored-image"></div>

查看更多
骚的不知所云
6楼-- · 2018-12-31 17:54

In most browsers, you can use filters :

  • on both <img> elements and background images of other elements

  • and set them either statically in your CSS, or dynamically using JavaScript

See demos below.


<img> elements

You can apply this technique to a <img> element :

#original, #changed {
    width: 45%;
    padding: 2.5%;
    float: left;
}

#changed {
    -webkit-filter : hue-rotate(180deg);
    filter : hue-rotate(180deg);
}
<img id="original" src="http://i.stack.imgur.com/rfar2.jpg" />

<img id="changed" src="http://i.stack.imgur.com/rfar2.jpg" />

Background images

You can apply this technique to a background image :

#original, #changed {
    background: url('http://i.stack.imgur.com/kaKzj.jpg');
    background-size: cover;
    width: 30%;
    margin: 0 10% 0 10%;
    padding-bottom: 28%;
    float: left;
}

#changed {
    -webkit-filter : hue-rotate(180deg);
    filter : hue-rotate(180deg);
}
<div id="original"></div>

<div id="changed"></div>

JavaScript

You can use JavaScript to set a filter at runtime :

var element = document.getElementById("changed");
var filter = 'hue-rotate(120deg) saturate(2.4)';
element.style['-webkit-filter'] = filter;
element.style['filter'] = filter;
#original, #changed {
    margin: 0 10%;
    width: 30%;
    float: left;
    background: url('http://i.stack.imgur.com/856IQ.png');
    background-size: cover;
    padding-bottom: 25%;
}
<div id="original"></div>

<div id="changed"></div>

查看更多
明月照影归
7楼-- · 2018-12-31 17:57

There's no need for a whole font set if you only need one icon, plus I feel it being more "clean" as an individual element. So, for this purpose, in HTML5 you can place a SVG directly inside the document flow. Then you can define a class in your .CSS stylesheet and access its background color with the fill property:

Working fiddle: http://jsfiddle.net/qmsj0ez1/

Note that, in the example, I've used :hoverto illustrate the behaviour; if you just want to change color for the "normal" state, you should remove the pseudoclass.

查看更多
登录 后发表回答