htmlcssgrayscaleblendingbackground-blend-mode

Apply a css -webkit-filter grayscale before using a background-blend-mode keeping the color


I'm trying to achieve a monochrome colored image on mouse hover, where the colors of the image are transformed to grayscale and the gray shades afterwards replaced with the shade of color i'm blending with.

It could look like this

To simulate this in photoshop you can grayscale a image add your desired color layer on top and blend it with screen mode.

As far as i understand css has this potential if you combine the css filter and the background-blend-mode, but the result will always be grayscale if you use the filter.

So i'm asking if there any other ways to get this blend, or to grayscale images before without the css filter


Solution

  • You can do it in one single step, using luminosity as the blend mode.

    In this mode, luminosity is taken from the front layer(the image), and the hue and saturation are taken from the background (here, a solid color)

    The following demo gives you also the posibility to asign the color filter thru the class

    .test {
        width: 400px;
        height: 200px;    
        margin: 10px;
        background-size: cover;
        background-image:  url(http://placekitten.com/1000/750);
    }
    
    .test:hover {
        background-blend-mode: luminosity;
    }
    
    .red {
        background-color: red;
    }
    
    .green {
        background-color: greenyellow;
    }
    <div class="test red"></div>
    <div class="test green"></div>

    Another solution, where black in the image gives full saturated color (instead of black). A little bit more complex to set up, but achievable.

    .test {
        width: 400px;
        height: 200px;    
        background-size: cover;
        background-color: white;
        background-image: linear-gradient(red, red), url(http://placekitten.com/1000/750);
        background-blend-mode: screen, luminosity;
    }
    <div class="test"></div>

    A way to have this effect as a reusable class. The image is already on the element, and we just set the class to set the effect and a separate class for the color.

    So the sequence needs to be:

    We need to use a pseudo element for the final blend, to make it easy to set all this with an independent class. this will be set with mix-blend instead of background-blend :

    #cat {
        width: 760px;
        height: 560px;
        background-image: url(http://placekitten.com/1000/750); 
    }
    
    .test {
        background-color: white;
        background-position: 0px 0px;
        background-size: cover;
        background-blend-mode: luminosity;
        position: relative;
    }
    
    .test:after {
        content: "";
        position: absolute;
        left: 0px;
        top: 0px;
        right: 0px;
        bottom: 0px;
        mix-blend-mode: screen;
        pointer-events: none;
    }
    
    .blue:after {
        background-color: blue;
    }
    <div class="test blue" id="cat"></div>