Change color of PNG image via CSS?

1,279,800

Solution 1

You can use filters with -webkit-filter and filter: Filters are relatively new to browsers but supported in over 90% of browsers according to the following CanIUse table: https://caniuse.com/#feat=css-filters

You can change an image to grayscale, sepia and lot more (look at the example).

So you can now change the color of a PNG file with filters.

body {
    background-color:#03030a;
    min-width: 800px;
    min-height: 400px
}
img {
    width:20%;
    float:left; 
     margin:0;
}
/*Filter styles*/
.saturate { filter: saturate(3); }
.grayscale { filter: grayscale(100%); }
.contrast { filter: contrast(160%); }
.brightness { filter: brightness(0.25); }
.blur { filter: blur(3px); }
.invert { filter: invert(100%); }
.sepia { filter: sepia(100%); }
.huerotate { filter: hue-rotate(180deg); }
.rss.opacity { filter: opacity(50%); }
<!--- img src http://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/500px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg -->
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="original">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="saturate" class="saturate">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="grayscale" class="grayscale">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="contrast" class="contrast">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="brightness" class="brightness">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="blur" class="blur">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="invert" class="invert">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="sepia" class="sepia">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="huerotate" class="huerotate">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="opacity" class="rss opacity">

Source

Solution 2

I found this great codepen example that you insert your hex color value and it returns the needed filter to apply this color to png

CSS filter generator to convert from black to target hex color

for example i needed my png to have the following color #1a9790

then you have to apply the following filter to you png

filter: invert(48%) sepia(13%) saturate(3207%) hue-rotate(130deg) brightness(95%) contrast(80%);

PS: The codepen is based on this brilliant answer by MultiplyByZer0 here: How to transform black into any given color using only CSS filters

all credits goes to him :clap:

Solution 3

You might want to take a look at Icon fonts. http://css-tricks.com/examples/IconFont/

EDIT: I'm using Font-Awesome on my latest project. You can even bootstrap it. Simply put this in your <head>:

<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet">

<!-- And if you want to support IE7, add this aswell -->
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome-ie7.min.css" rel="stylesheet">

And then go ahead and add some icon-links like this:

<a class="icon-thumbs-up"></a>

Here's the full cheat sheet

--edit--

Font-Awesome uses different class names in the new version, probably because this makes the CSS files drastically smaller, and to avoid ambiguous css classes. So now you should use:

<a class="fa fa-thumbs-up"></a>

EDIT 2:

Just found out github also uses its own icon font: Octicons It's free to download. They also have some tips on how to create your very own icon fonts.

Solution 4

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.

Solution 5

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>
Share:
1,279,800
John Slegers
Author by

John Slegers

I'm John Slegers, full stack web developer from Belgium. Prefered tech Stats Where to find me

Updated on April 12, 2022

Comments

  • John Slegers
    John Slegers about 2 years

    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?

    • jakub.g
      jakub.g over 12 years
      You can set background-color CSS property. You can create non-transparent part that will be fixed, and transparent part of image which will be filled by any color you like via CSS. Is that what you want to achieve?
    • Unknown artist
      Unknown artist over 12 years
      @qbk, this is worth an answer, not just a comment. And you beat me by 1 second, technically.
    • chrscblls
      chrscblls over 7 years
      You can use psuedo-elements with a blending mode to recolor any icon that is 100% black or 100% white (background stays transparent). See my answer here: stackoverflow.com/a/39796437/1472114
    • gd1
      gd1 about 3 years
      For those looking for an actual, up-to-date answer that doesn't involve those ghastly "filters" which are totally not meant for this, look no further than: stackoverflow.com/a/32736304/671092 You can skip the rest: you're welcome.
  • feeela
    feeela over 12 years
    Is that part of any (yet-to-come) standard, as I didn't found any information unrelated to Webkit, or is it just Apple-flavour? It seems that the W3 is suggesting SVG for such usecases: w3.org/TR/SVG/masking.html
  • Admin
    Admin over 12 years
    I want the white part colored differently, not the transparent part.
  • Jules Colle
    Jules Colle over 11 years
    best solution I found so far. Too bad it will only work if you use a solid background-color on your websites
  • Charles Goodwin
    Charles Goodwin over 10 years
    Sadly this seems to be webkit only and the blog cheats by using composited images rather than actual examples. This answer is a bit of red herring.
  • Charles Goodwin
    Charles Goodwin over 10 years
    @Wesley you need to invert the image then (so the white bit becomes transparent and the rest white) which you can do using your favourite image editor and masks.
  • Trilarion
    Trilarion almost 10 years
    So short answer is that there isn't any general solution for the majority of browsers.
  • yvan vander sanden
    yvan vander sanden almost 9 years
    +1 for out of the box thinking. And nowadays there are easy to use online apps to help you create a webfont from an (svg) image.
  • ki9
    ki9 about 8 years
    But will huerotate or saturate actually do anthing to a white image?
  • Stan
    Stan about 8 years
    2016 Update: this now works in almost all browsers except IE: caniuse.com/#feat=css-filters
  • zakius
    zakius about 8 years
    When I try affecting background color of element this way it just gets completely replaced, I expected it to help me achieving hover depending on default bg color easily but it seems that won't work
  • AsGoodAsItGets
    AsGoodAsItGets almost 8 years
    As nice as all these color filters are, none (or no combination) of them seem to be able to go from white or black to another "vivid" color (e.g. red, green, etc.) :( Maybe I'm missing something?
  • datatype_void
    datatype_void almost 8 years
    @AsGoodAsItGets I am using filters to color png images across a range of vivid colors. hue-rotate and brightness are particularly useful together. For example, to achieve a gold/yellow color: .class-declaration { filter: hue-rotate(-78deg) brightness(1.6); }. If you were to do something like .class-declaration { filter: hue-rotate(-5deg) brightness(0.6); } , you would end up with a green color. There has been no color I cannot attain by messing with these filters.
  • datatype_void
    datatype_void almost 8 years
    Of course, I should probably mention that all of my png start off pale green, not white.
  • AsGoodAsItGets
    AsGoodAsItGets almost 8 years
    @datatype_void I was very specific, I mentioned black or white. Can you make a combination of filters that takes you to any color starting from pure black or white?
  • datatype_void
    datatype_void almost 8 years
    @AsGoodAsItGets: I don't see how starting with a black or white image matters since you could just start with a certain set of properties to appear black, then apply different rules to achieve the desired color. Starting with a green image as I have been doing, you can get black or white by turning the brightness down to zero or up to more extreme values such as 8, 25, et cetera. From there you can get to any vivid color by adjusting hue-rotate and brightness. If you played around with the CSS in the browser for all of five minutes you'd see that this is possible.
  • AsGoodAsItGets
    AsGoodAsItGets almost 8 years
    @datatype_void Sometimes you don't control the starting image yourself. So, it seems that you agree that my point is valid, you can't get to any color starting from black or white. Oh, and I played for way more than 5 minutes to reach this conclusion.
  • AsGoodAsItGets
    AsGoodAsItGets almost 8 years
    @datatype_void Plus, the OP asked specifically about a starting image with white color over transparent background.
  • datatype_void
    datatype_void almost 8 years
    @AsGoodAsItGets: No, you're correct, you can't get color out of something that is a combination of all colors or the lack of colors--respectively--with simple filter effects. But for the 98% of the time that you can just pop open PhotoShop and change the base color to something else, you can get any color you want from that starting image. I was merely providing an alternative method that worked for my case and meeting your snarkiness with equal force.
  • datatype_void
    datatype_void almost 8 years
    If you are willing to use an alternative method that only works with webkit, you can use masks as other answers suggest but don't demonstrate: codepen.io/datatype_void/pen/mEXaJQ
  • chrscblls
    chrscblls over 7 years
    You can use psuedo-elements with a blending mode to recolor any icon that is 100% black or 100% white (like the OP). See my answer here: stackoverflow.com/a/39796437/1472114
  • chrscblls
    chrscblls over 7 years
    I rehosted the image off of imgur, was having some troubles loading it.
  • Synetech
    Synetech over 7 years
    The question was about colorizing a white image with a transparent background. hue-rotate does not work on white.
  • MaxPRafferty
    MaxPRafferty about 7 years
    Man you are getting robbed on this answer. Anyone looking to colorize images beyond what filter: hue-rotate can do - this is the way to do it.
  • logidelic
    logidelic almost 7 years
    In the latest version of Chrome, it looks like the (transparent) background is also getting set to the color. In the linked example, when I hover, I just see an opaque pink square... Works well in Firefox.
  • tatsu
    tatsu over 6 years
    also specify that you can do stuff like this : .gifcorrect{ filter: invert(28%) sepia(100%) hue-rotate(-180deg) saturate(3); } which means you CAN go from black & transparent or grayscale to color and it works even on animated gifs
  • Alex
    Alex about 6 years
    @CharlesGoodwin That only works then the image is placed in a white background.
  • brandito
    brandito almost 6 years
    If <a class="icon-thumbs-up"></a> is the old class name and <a class="fa fa-thumbs-up"></a> is the new one I don't think it makes the CSS smaller, I can see an additional whitespace between fa and fa-thumbs-up, add atleast 1 additional byte on to that CSS file if I'm not mistaken?
  • Steven Lu
    Steven Lu almost 6 years
    @chrscblls The link is dead.
  • SadeepDarshana
    SadeepDarshana over 5 years
    what of the browser support in 2018AUG?
  • Y.K.
    Y.K. over 5 years
    Font Awesome was great in it's day, unfortunately its render blocking, which makes google and it's users unhappy. We first addressed this by removing unused fonts from both the CSS and the binary font files, reducing data by around half. We're now in the process of removing altogether and replacing with a simple sprite, which is not render blocking (DOM and CSSOM process faster, making elements on page appear faster), and will reduce data by another 75%, down to 6KB. FA is around 100KB. CSS masks may help in our case, but probably unnecessary.
  • Daniel
    Daniel over 5 years
    This works, I voted Up. But just for the record it does have some problems like can´t size the background image, can´t position the image and it does repeat.
  • Muthukumar Anbalagan
    Muthukumar Anbalagan over 5 years
    Ohh, I really didn't try those... try below link. developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-im‌​age thanks, Daniel
  • André Werlang
    André Werlang over 5 years
    This answer is inexplicably overrated. If OP was about replacing a given color with a pseudo-random color, that's the answer.
  • Anjan Biswas
    Anjan Biswas over 5 years
    I have change color to white from blue using this code: filter: invert(1%) sepia(1%) saturate(1%) hue-rotate(1deg) brightness(1000%) contrast(80%);
  • Vic Seedoubleyew
    Vic Seedoubleyew almost 5 years
    Didn't work for me. I can't tell why, I copy pasted exactly
  • rolznz
    rolznz almost 5 years
    @VicSeedoubleyew the snippet works fine. Inspect your div using dev tools to ensure your CSS is actually being applied. Also, make sure the URL to your image is valid if you're not using the one I provided. EDIT: If the snippet doesn't work for you, you might be using a browser that is either out of date or doesn't support the linear-gradient function.
  • Jackie Degl'Innocenti
    Jackie Degl'Innocenti almost 5 years
    Author deserve a statue! (note the: brightness(0) saturate(100%) optional prepend that kills any doubt)
  • Mego
    Mego over 4 years
    Doesnt work. The browser show all filters one by one and stay on contrast
  • dwjohnston
    dwjohnston over 4 years
    If anyone needs it, here is a TS conversion of this code gist.github.com/dwjohnston/7e60bf5d4b6c071cd869f9f346241c08
  • djdance
    djdance over 4 years
    repeat drop-shadow 2-3 times to make it stronger
  • Richard KeMiKaL GeNeRaL Denton
    Richard KeMiKaL GeNeRaL Denton over 4 years
    GENIUS SOLUTION, looks a little messy in the CSS, but with a comment, it's perfectly understandable. Thanks!
  • swisswiss
    swisswiss about 4 years
    wont work to get exact color, it is always some sort of mix between the original color and the new one.
  • SMAG
    SMAG about 4 years
    this approach slightly distorts the image and it gets worse every time drop-shadow is applied. Like making a copy of a copy the results are different from the original.
  • Peanuts
    Peanuts about 4 years
    Some more context here: inserthtml.com/2012/06/css-filters
  • Jealie
    Jealie almost 4 years
    perfect for my purpose (I did not need the exact hue)
  • user3808307
    user3808307 almost 4 years
    @datatype_void if I want to go to #ff0000 (just an example) from, say, white, is there a table or something that helps me achieve a specific color?
  • ojathelonius
    ojathelonius over 3 years
    This works for black backgrounds or images. For white elements, try fiddling with the invert parameter to get the proper color.
  • Nosajimiki
    Nosajimiki over 3 years
    @swisswiss Don't repeat the dropshadow, add a saturate filter with >100% so it looks something like "filter: opacity(0.5) drop-shadow(0 0 0 blue) saturate(1000%);" This does everything with a single pass which will solve the issue that SMAG brings up.
  • Marc Maxmeister
    Marc Maxmeister about 3 years
    Nice hack! Allows me to take any of the nouns project pngs and make them whatever color I want, if I drop-shadow twice.
  • Sven Eberth
    Sven Eberth almost 3 years
    Did you forget to link the codepen example? However, it's better to use the stack snippet to include all the code in the answer.
  • Ethan Ray
    Ethan Ray over 2 years
    Oh yeah no this one, this is the answer. This is absolutely brilliant. Too bad I only need this for one super niche thing. This is one of those elegant solutions I wish I needed more often.
  • Burak Day
    Burak Day over 2 years
  • Adam Pietrasiak
    Adam Pietrasiak over 2 years
    This solution does not allow anything to be 'under the icon' as it has solid background when changing the color
  • Salix
    Salix over 2 years
    On the codepen linked, there's a link to an updated version using mask which works better and solve that problem.
  • Salix
    Salix over 2 years
    @AdamPietrasiak Added link to pen and a snippet example. This method allow things under and, once every other browser catch up to firefox, to use luminence as alpha too!
  • Salix
    Salix over 2 years
    oops haha, forgot what my original problem was, and this doesn't fix it since I couldn't have the url in my css... Well, guess I can add it with JS but I liked that I didn't have to ^^'
  • Salix
    Salix over 2 years
    for icon with alpha, can replace <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" /> with <feComposite in="flood" in2="SourceAlpha" operator="atop"/> (works on white, color and black)
  • zehawk
    zehawk about 2 years
    The codepen is based on this brilliant answer by MultiplyByZer0 here: stackoverflow.com/questions/42966641/…
  • Aaron Ash
    Aaron Ash almost 2 years
    @Salix exactly what I was looking for to emulate iOS image tinting - thanks!
  • Bullsized
    Bullsized almost 2 years
    whoever pulled this off is a God!
  • Salix
    Salix almost 2 years
    @AaronAsh glad my comment on an old answer was useful :)