Darkening an image with CSS (In any shape)
Asked Answered
M

5

67

So I have seen quite a few ways to darken images with CSS, including ones with rounded corners, but my problem is different.

Let's say I have an .png image that looks like a little dog (just go with it, I don't have any good examples), when I place it on my page, I give it dimensions of 100 x 100.

But I can't just overlay something on it, or tint the entire image, as it will cause the background of the dog to be tinted as well, which looks ugly.

Is it possible to tint an image of arbitrary shape with CSS?

(I'm assuming you understand my point, and useless code is not necessary)

Thanks!

Misalliance answered 2/4, 2013 at 13:36 Comment(14)
Give relative position to image and add a div with absolute position insideDale
You'll need to make a png the same size with a silhouette of the dog and overlay it.Inimitable
@Morpheus, But how would this help? If the position is 100px x 100px, and the image is the shape of a dog, with the rest of the image transparent, how it adding a div with it's size at 100px x 100px going to help. Perhaps I miss understanding you though. I admit I don't do web-based languages very often.Misalliance
@gaynorvader, Yes, I could do this, but I really would prefer not too if possible. If necessary I will though.Misalliance
if you add .overlay{background: black; opacity: 0.2}Dale
@Morpheus, And this will not affect the transparent part of the image?Misalliance
Applying SVG filters would be a good solution for modern browser; otherwise one could implement it in Canvas. Regarding compatibility with legacy browsers, probably just using CSS sprites would be a compromise.Unsocial
Ignore me, it will...Dale
@CBroe, If you could post an answer with some more detail on this, that sounds like a good solution. I only care about modern browsers here, no IE either.Misalliance
have you thought about using opacity on the image? I know this will more lighten than darken the image but that might be acceptable in this caseXuthus
@Josiah, It may be possible to dynamically detect the non-white or non-transparent pixels in a png using javascript and then progamatically fill in a new png with the silhouette, but it'd be more work than it's worth unless you were doing it with a lot of images.Inimitable
@SeanDunwoody, No, I can not alter the opacity, my image is light enough by default, I need to darken it instead. Though I may resort to this.Misalliance
https://mcmap.net/q/296792/-brightness-filter-in-firefox-and-opera-without-svg-file, developer.mozilla.org/en-US/docs/…Unsocial
@SeanDunwoody, Actually, I take it it back. That actually might be the best approach for this exact circumstance. You should post that as an answer.Misalliance
X
28

You could always change the opacity of the image, given the difficulty of any alternatives this might be the best approach.

CSS:

.tinted { opacity: 0.8; }

If you're interested in better browser compatability, I suggest reading this:

http://css-tricks.com/css-transparency-settings-for-all-broswers/

If you're determined enough you can get this working as far back as IE7 (who knew!)

Note: As JGonzalezD points out below, this only actually darkens the image if the background colour is generally darker than the image itself. Although this technique may still be useful if you don't specifically want to darken the image, but instead want to highlight it on hover/focus/other state for whatever reason.

Xuthus answered 2/4, 2013 at 13:54 Comment(6)
Also wrap the image with a div with background: black;Prejudicial
This wont make an image darker than it is (opacity: 1;) It's actually lightening.Buster
If the image is displayed over a dark background, it will seem to have the effect of darkening the image (as more of the darker background will show through). You can see an example here: jsfiddle.net/mvhfxrm1 the top image has a colour of #CCCCCC while the bottom image has a colour of #676767Xuthus
@SeanDunwoody right, unfortunately for images shaped different than a square it wont work (images with transparencies) since the dark background is going to be visible all the time. But it can work for squared images.Buster
It depends on the complexity of the shape, if it's simply rounded corners then you can apply these as styles to the background container (using border-radius). Although if you have a complex picture like a person on a transparent background then I can't really think of a way around that. The best way to approach that might be to use a sprite or something to swap images out creating this effect, but there might be a better way to do this, I'm not as up to date on CSS as I used to be unfortunately.Xuthus
tint means adding white. if background color is white, decreasing the opacity makes image even brighterNottinghamshire
E
211

Easy as

img {
  filter: brightness(50%);
}
Estray answered 10/12, 2016 at 14:55 Comment(3)
This is the way to go, if not too worried about old IEClydesdale
Note: if this makes your image look too dull, you may want to increase the saturation simultaneously, e.g. filter: brightness(75%) saturate(140%);Parcheesi
Sadly it doesnt work well when image is png on transparent/white backgroundHendecahedron
X
28

You could always change the opacity of the image, given the difficulty of any alternatives this might be the best approach.

CSS:

.tinted { opacity: 0.8; }

If you're interested in better browser compatability, I suggest reading this:

http://css-tricks.com/css-transparency-settings-for-all-broswers/

If you're determined enough you can get this working as far back as IE7 (who knew!)

Note: As JGonzalezD points out below, this only actually darkens the image if the background colour is generally darker than the image itself. Although this technique may still be useful if you don't specifically want to darken the image, but instead want to highlight it on hover/focus/other state for whatever reason.

Xuthus answered 2/4, 2013 at 13:54 Comment(6)
Also wrap the image with a div with background: black;Prejudicial
This wont make an image darker than it is (opacity: 1;) It's actually lightening.Buster
If the image is displayed over a dark background, it will seem to have the effect of darkening the image (as more of the darker background will show through). You can see an example here: jsfiddle.net/mvhfxrm1 the top image has a colour of #CCCCCC while the bottom image has a colour of #676767Xuthus
@SeanDunwoody right, unfortunately for images shaped different than a square it wont work (images with transparencies) since the dark background is going to be visible all the time. But it can work for squared images.Buster
It depends on the complexity of the shape, if it's simply rounded corners then you can apply these as styles to the background container (using border-radius). Although if you have a complex picture like a person on a transparent background then I can't really think of a way around that. The best way to approach that might be to use a sprite or something to swap images out creating this effect, but there might be a better way to do this, I'm not as up to date on CSS as I used to be unfortunately.Xuthus
tint means adding white. if background color is white, decreasing the opacity makes image even brighterNottinghamshire
D
22

if you want only the background-image to be affected, you can use a linear gradient to do that, just like this:

  background: linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .5)), url(IMAGE_URL);

If you want it darker, make the alpha value higher, else you want it lighter, make alpha lower

Donnelly answered 30/7, 2019 at 13:18 Comment(2)
Thank you, as this allowed me to darken my <main> element's image without darkening the content of the page. Best answer!Insurgence
I'm glad you liked. Always happy to be useful!Donnelly
M
2

I would make a new image of the dog's silhouette (black) and the rest the same as the original image. In the html, add a wrapper div with this silhouette as as background. Now, make the original image semi-transparent. The dog will become darker and the background of the dog will stay the same. You can do :hover tricks by setting the opacity of the original image to 100% on hover. Then the dog pops out when you mouse over him!

style

.wrapper{background-image:url(silhouette.png);} 
.original{opacity:0.7:}
.original:hover{opacity:1}

<div class="wrapper">
  <div class="img">
    <img src="original.png">
  </div>
</div>
Monophysite answered 9/5, 2014 at 15:30 Comment(1)
second line should be .original{opacity:0.7;}Contumelious
C
0

Webkit only solution

Quick solution, relies on the -webkit-mask-image property. -webkit-mask-image sets a mask image for an element.

There are a few gotchas with this method:

  • Obviously, only works in Webkit browsers
  • Requires an additional wrapper to apply the :after psuedo-element (IMG tags can't have :before/:after pseudo elements, grr)
  • Because there's an additional wrapper, I'm not sure how to use the attr(…) CSS function to get the IMG tag URL, so it's hard-coded into the CSS separately.

If you can look past those issues, this might be a possible solution. SVG filters will be even more flexible, and Canvas solutions will be even more flexible and have a wider range of support (SVG doesn't have Android 2.x support).

Crispin answered 2/4, 2013 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.