23

For example, it has an image with a transparent background:

Enter image description here

And I would like to add an gray overlay (for example, a div, or canvas...) on it:

Enter image description here

But I want the overlay ignores transparent area on an image automatically:

Enter image description here

Can pure HTML and CSS (for example, by div, canvas...) do this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ggrr
  • 7,737
  • 5
  • 31
  • 53
  • 2
    You can do it using svg – Akshay Dec 16 '16 at 09:08
  • This is basically [Is it possible to apply CSS to half of a character?](http://stackoverflow.com/questions/23569441/is-it-possible-to-apply-css-to-half-of-a-character) but with an image. – BoltClock Dec 16 '16 at 16:01

4 Answers4

24

Try the overlay blend-mode. Or multiply! (Not supported by IE or Edge, thanks @Stilltorik)

.multiplied {
  background-color: blue;
  width:250px;
  height: 100px;
  margin-top: -100px;
  mix-blend-mode: overlay;
}
<div>
  <img src='https://i.stack.imgur.com/4yUEW.png'/>
  <div class='multiplied'></div>
</div>
Carele
  • 756
  • 3
  • 13
  • 9
    Careful though, it is not supported by IE, or edge: http://caniuse.com/#feat=css-mixblendmode – Stilltorik Dec 16 '16 at 13:10
  • 3
    Pretty close, though unfortunately none of the available blending modes precisely reproduces the desired result. It's also highly dependent on the image, and the background that the image appears on. Whether any of this is important depends on the asker, though it's evident that 18 other users either did not notice or don't care, judging by the vapid "+1" comments above. – BoltClock Dec 16 '16 at 15:46
  • Thanks for noting that it is not supported by Edge & IE. I'm editing. @BoltClock Yes. That is precisely why i offered both. I don't know any other way to achieve such a render so i usually mess up with blend mode and the colors themselves to get the appropriate results and the right final colour. Not the ideal way indeed but the simplest without too many side effects. – Carele Dec 19 '16 at 14:46
2

A somewhat hacky way:

.alpha-mask {
  mask-image: url(https://i.stack.imgur.com/FwTzE.png);
  -webkit-mask-image: url(https://i.stack.imgur.com/FwTzE.png);
  mask-mode: alpha;
  -webkit-mask-mode: alpha;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}

.overlay {
  background-color: #000;
  position: absolute;
  top: 120px;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0.2;
}
<article class="alpha-mask">
  <img class="alpha-target" src="https://i.stack.imgur.com/FwTzE.png" />
  <div class="overlay alpha-target">
  </div>
</article>

See it working.

Ivan Chaer
  • 6,980
  • 1
  • 38
  • 48
0

Without knowing the full use case for this question, I would say the answer is "Yes, but cross browser compatibility will be a nuisance."

The two other answers posted here show ways it might be accomplished if compatibility is not an issue, but I think this is something that can be done much more simply by some creative photoshop and then layered elements.

What I would do:

Photoshop: Take your base image (which I am assuming is PNG since it has an alpha channel) and load it into photoshop. Select the area you wish to mask. edit > copy merged. Make a new layer and edit > paste. Alter the color of this new layer to be the color you want the masked overlay to be and add your alpha channel effect. Make sure the default background is turned off and then save the new layer as a PNG.

HTML:

<div class="container">
  <div class="original-image"></div>
  <div class="mask"></div>
</div>

CSS:

.container {
  height: 300px;
  width: 300px;
  position: relative;
}

.original-image {
  height: 300px;
  width: 300px;
  background : url(../images/myimage.png) no-repeat top center;
}

.mask {
  height: 300px;
  width: 300px;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1; //or more depending on what else is going on in the layout
  background : url(../images/mask.png) no-repeat top center;
}

It's important in this example for the container to have the same dimensions as the image and mask so that the absolute positioning aligns the mask over your image properly. Making the images into backgrounds allows you to fill the divs with content like type. The main advantage to doing it this way, rather than with the CSS suggested elsewhere here, is that this should work on almost every browser.

Jason B.
  • 119
  • 3
0

Here is a canvas based approach:

HTML:

<canvas id="canvas" width="500" height="500"></canvas>

JS:

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var star = new Image();
star.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Light_blue_star.svg/500px-Light_blue_star.svg.png";

star.onload = function() {
  //Draw our image on the canvas
  ctx.drawImage(star, 0, 0);
  //Blend a rectangle over it
  ctx.fillStyle = '#f00ba2';
  ctx.globalCompositeOperation = "multiply";
  ctx.fillRect(0, 250, 500, 250);
  //Clip the output with the non transparent pixels of the original image with destination-in compositing mode
  ctx.globalCompositeOperation = "destination-in";
  ctx.drawImage(star, 0, 0);
}