Balázs Varga
Balázs Varga

Reputation: 1856

Is there any way to colorize a white PNG image with CSS only?

I know there are many css filters out there especially for webkit, but I can't find a solution for colorize a white (#FFFFFF) image. I've tried some combination of the filters, but none of them make my image colorized. I can only change the image in the range of grayscale, or sepia.

So my question is: Is there any way to change my totally white png to (for example) red using css only?

Like shown on this image:

enter image description here

Upvotes: 42

Views: 71360

Answers (4)

Michael Mullany
Michael Mullany

Reputation: 31715

This can be done with a CSS filter that references an SVG Filter. Here is the SVG filter (the "1 1 1" in the first line of values converts the blue and green channels to red.)

<svg width="800px" height="600px">
    <filter id="redden" color-interpolation-filters="sRGB">
        <feColorMatrix type="matrix" values="1 1 1 0 0 
                                             0 0 0 0 0 
                                             0 0 0 0 0 
                                             0 0 0 1 0"/>
    </filter>
    
    <image filter="url(#redden)" width="190" height="400" 
        preserveAspectRatio="xMinYMin slice" 
        xlink:href="https://i.sstatic.net/e6MUC.jpg"/>
</svg>

Upvotes: 6

once
once

Reputation: 1399

i tried to color my white cloud picture following @zekkai's answer, and then i wrote a filter generator.

var slider_huerotate = document.getElementById("slider_huerotate");
var slider_brightness = document.getElementById("slider_brightness");
var slider_saturate = document.getElementById("slider_saturate");
var slider_sepia = document.getElementById("slider_sepia");

var output = document.getElementById("demo");
var cloud = document.getElementById('cloud');
let [brightness, sepia, saturate, huerotate] = ["100", "80", "100", "360"];
var filtercolor = `brightness\(${brightness}%\) sepia\(${sepia}\) saturate\(${saturate}\) hue-rotate\(${huerotate}deg\)`

// Display the default slider value
output.innerHTML = filtercolor; 

// Update the current slider value (each time you drag the slider handle)
slider_huerotate.oninput = function() {
  huerotate = this.value;
  var filtercolor = `brightness\(${brightness}%\) sepia\(${sepia}\) saturate\(${saturate}\) hue-rotate\(${huerotate}deg\)`
  cloud.style.filter = filtercolor;
  output.innerHTML = filtercolor;
}

slider_brightness.oninput = function() {
  brightness = this.value;
  var filtercolor = `brightness\(${brightness}%\) sepia\(${sepia}\) saturate\(${saturate}\) hue-rotate\(${huerotate}deg\)`
  cloud.style.filter = filtercolor;
  output.innerHTML = filtercolor;
}

slider_sepia.oninput = function() {
  sepia = this.value;
  var filtercolor = `brightness\(${brightness}%\) sepia\(${sepia}\) saturate\(${saturate}\) hue-rotate\(${huerotate}deg\)`
  cloud.style.filter = filtercolor;
  output.innerHTML = filtercolor;
}

slider_saturate.oninput = function() {
  saturate = this.value;
  var filtercolor = `brightness\(${brightness}%\) sepia\(${sepia}\) saturate\(${saturate}\) hue-rotate\(${huerotate}deg\)`
  cloud.style.filter = filtercolor;
  output.innerHTML = filtercolor;
}
.slider {
  -webkit-appearance: none;
  width: 350px;
  height: 15px;
  border-radius: 5px;
  background: #d3d3d3;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #4CAF50;
  cursor: pointer;
}

.slider::-moz-range-thumb {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #4CAF50;
  cursor: pointer;
}

img {
  width: 300px;
  z-index: 100;
  filter: brightness(100%) sepia(80) saturate(100) hue-rotate(360deg);
  padding: 70px 25px 50px 25px;
}

.wrapper {
  width: 600px;
  height: 500px;
  padding: 50px;
  font-size: small;
}

.slidecontainer_vertical {
  margin-top: 50px;
  transform: translate(0, 300px) rotate(270deg);
  -moz-transform: rotate(270deg);
}

.left {
  width: 50px;
  height: 300px;
  float: left;
}

.cloud {
  width: 100%;
}

.middle {
  width: 350px;
  height: 300px;
  float: left;
  margin: 0 auto;
}

.right {
  width: 50px;
  height: 300px;
  float: left;
}

#demo {
  width: 100%;
  text-align: center;
  padding-bottom: 20px;
  font-family: 'Handlee', cursive;
}
<head>
  <link href="https://fonts.googleapis.com/css?family=Handlee" rel="stylesheet">
</head>
<div class="wrapper">
  <div class="left">
    <div class="slidecontainer_vertical">
      <input type="range" min="0" max="360" value="360" class="slider" id="slider_huerotate">
    </div>
  </div>
  
  <div class="middle">
    <div class="slidecontainer">
      <input type="range" min="0" max="100" value="100" class="slider" id="slider_brightness">
    </div>

    <div id="cloud">
      <img src="https://docs.google.com/drawings/d/e/2PACX-1vQ36u4x5L_01bszwckr2tAGS560HJtQz4qblj0jnvFUPSgyM9DAh7z_L3mmDdF6XRgu8FkTjqJKSNBQ/pub?w=416&amp;h=288">
    </div>
    <div id="demo"></div>

    <div class="slidecontainer">
      <input type="range" min="0" max="100" value="80" class="slider" id="slider_sepia">
    </div>
  </div>
  
  <div class="right">
    <div class="slidecontainer_vertical">
      <input type="range" min="0" max="100" value="100" class="slider" id="slider_saturate">
    </div>
  </div>
</div>

Upvotes: 3

zekkai
zekkai

Reputation: 513

I recently have the same question and I think this approach is worth sharing for future readers. Try this

filter: brightness(50%) sepia(100) saturate(100) hue-rotate(25deg);

Brightness will darken the image, sepia will make it a bit yellowish, saturate to increase the color, and lastly hue-rotate to change the color. It's not cross browser friendly though:

Here are some useful tips and tools that I've used when I work with images/icons using css:

  • If you have the svg version of the image, you can convert them to font icons using this tool https://icomoon.io/ . To change color you just need color:#f00; just like font colors.
  • If you need to achieve this effect for hover state, Use red image with filter: brightness(0) invert(); on NON-hover state, and filter: brightness(1); on hover state. Hovever this will still won't work on IE
  • Use sprite sheet. You can create yourself using image editing tool or use sprite sheet generators available online. Then, you can use SpriteCow to get the css for every sub-image of your spritesheet.

Upvotes: 36

James Montagne
James Montagne

Reputation: 78650

This can be done with css masking, though unfortunately browser support is really bad (I believe webkit only).

http://jsfiddle.net/uw1mu81k/1/

-webkit-mask-box-image: url(http://yourimagehere);

Because your image is all white, it is a perfect candidate for masking. The way the mask works is that wherever the image is white, the original element is shown as normal, where black (or transparent) the original element is not shown. Anything in the middle has some level of transparency.

EDIT:

You can also get this to work in FireFox with slight help from svg.

http://jsfiddle.net/uw1mu81k/4/

div {
  width: 50px;
  height: 50px;
  mask: url(#mymask);
  -webkit-mask-box-image: url(http://www.clker.com/cliparts/F/5/I/M/f/U/running-icon-white-on-transparent-background-md.png);
}
<div style="background-color: red;"></div>
<div style="background-color: blue;"></div>
<div style="background-color: green;"></div>
<div style="background-color: orange;"></div>
<div style="background-color: purple;"></div>

<svg height="0" width="0">
  <mask id="mymask">
    <image id="img" xlink:href="http://www.clker.com/cliparts/F/5/I/M/f/U/running-icon-white-on-transparent-background-md.png" x="0" y="0" height="50px" width="50px" />
  </mask>
</svg>

Upvotes: 33

Related Questions