I am trying to desaturate the background image of a div while leaving the images within that same div saturated. I've found one example close to what I'm trying to do (except w/ blur) but have tried multiple variations of it w/ no success.
In the code below, the .desaturate class correctly applies the filter attributes and turns bg image into b&w. The other image w/in this section tag are inheriting the desaturate as would be expected, but when I try to "re-saturate" through the img.saturate class it is not being applied. I've whittled down my code to as short/basic as it can get to explain what I am trying to do. Any ideas or solution how this can be done is appreciated.
<html>
<style>
.desaturate {
width: 100%;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
/*grayscale for background image*/
-webkit-filter: grayscale(1);
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
filter: gray;
filter: grayscale(100%);
filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale");
}
img.saturate {
filter: none !important;
width: 300px;
height: 200px;
-webkit-filter: grayscale(0%) !important;
-moz-filter: grayscale(0%) !important;
-ms-filter: grayscale(0%) !important;
-o-filter: grayscale(0%) !important;
}
</style>
<body>
<section class="desaturate" style="background-image: url('bg-img-1.jpg');">
<div class="row">
<div class="col-md-12">
<img src="img-2.jpg" class="img-responsive saturate" alt="" />
</div>
</div>
</section>
</body>
</html>
Saturation works in the same way as opacity does, you can't apply the effect to a parent and then undo it in a child. Your best option would probably be to make the grayscaled image a child of your section but not a parent of the image:
<section>
<figure class="desaturate" style="background-image: url('bg-img-1.jpg');"></figure>
<div class="row">
<div class="col-md-12">
<img src="img-2.jpg" class="img-responsive saturate" alt="" />
</div>
</div>
</section>
Your other option would be to inherit the background in a ::before
or ::after
pseudo element and apply the filter there:
.desaturate {
width: 100%;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
position: relative;
}
.desaturate:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: inherit;
/*grayscale for background image*/
-webkit-filter: grayscale(1);
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
filter: gray;
filter: grayscale(100%);
filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale");
}
You can see a demo here: http://codepen.io/Godwin/pen/ogLPvR.
Edit: Just for sake of interest, there is another way of doing this but it doesn't have high browser support yet:
.desaturate {
width: 100%;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
/*grayscale for background image*/
background-color: #FFF;
background-blend-mode: luminosity, normal;
}
Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/background-blend-mode
Example: http://codepen.io/Godwin/pen/raLZVr
Support: http://caniuse.com/#feat=css-backgroundblendmode
Make your background image a child
With your background image as a child, then you can apply a filter
on the element.
filter: grayscale(60%);
-webkit-filter: grayscale(60%);
-moz-filter: grayscale(60%);
-ms-filter: grayscale(60%);
-o-filter: grayscale(60%);
Alternatively, maintain your HTML structure, but only target the background-image...
Concerning background image's, filters aren't available, however you can get the same saturation effect using this trick with background-blend-mode
.
Usually background-blend-mode
is on-or-off (ie you cannot define percentage), however with the below trick you can actually get variable saturation:
background: linear-gradient(rgba(0,0,0,0.6),rgba(0,0,0,0.6)), url(image.jpg);
background-blend-mode: saturation;
This will give you a 60% desaturation only on the background image, using background-blend-mode
. The key is using linear-gradient, with opacity set on the colors. I can't seem to replicate the same effect not using a gradient (ie a solid color with opacity).
Browser support:
Both filter
and background-blend-mode
have weaker support in IE/Edge, so perhaps use separate CSS rules for those browsers (as described in tons of other posts).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With