It is because css greyscale() is for filtering image loaded with <img>
. Updated as follow, it does WORK for CSS background except HTML and Body tag. So I try to wrap up all the situations here AFAIK.
Situation 1 - background image + blend
For background image, you need to apply other tricks like background-blend-mode
property. You may refer some example online such as this
body {
background-image: linear-gradient(black, black), url(../img/ejager.jpg);
background-size: cover;
background-blend-mode: saturation;
}
Since your image is relative, so I use free online image as example.
body {
/* free image from https://pixabay.com/photos/flower-meadow-daisy-nature-flowers-4999277/ */
background-image: url(https://cdn.pixabay.com/photo/2020/04/03/15/27/flower-meadow-4999277_1280.jpg), linear-gradient(black, black);
background-size: cover;
background-blend-mode: saturation;
}
The principal behind this method:
The background-blend-mode
CSS property sets how an element's background images should blend with each other and with the element's background color.
background-image property support multiple background images since quite a long time.
The above example could be replaced with a normal black background image. For convenient sake, the example use this to create a black background.
The linear-gradient() CSS function creates an image consisting of a progressive transition between two or more colors along a straight line. Its result is an object of the data type, which is a special kind of .
As a result, it could be seen as a black background image with another image together and then use the blend filter to blend their saturation together.
According to the blend definition.
Creates a color with the saturation of the source color and the hue and luminosity of the backdrop color. Painting with this mode in an area of the backdrop that is a pure gray (no saturation) produces no change.
In this case, the saturation of the source color
is the saturation of black
and the hue and luminosity of the backdrop color
(the flower image)
It then preserves the flower image but with black and white effect.
Situation 2 - filter a image tag
Here is example of greyscale for image tag
img {
filter: grayscale(1);
}
<img src="https://cdn.pixabay.com/photo/2020/04/03/15/27/flower-meadow-4999277_1280.jpg" alt="">
Edited: After a thorough test with different filters. There is a few characteristic found as follow.
Situation 3 - Apply filter to html and body tag.
Filter is not working for background-image in HTML or Body tag.
However, it works if you setup the background image in a psuedo element.
- html, Safari works, FF, Chrome doesn't
- body, Safari, FF, Chrome doesn't
- html::before - before all content inside html
- html::after - theoretically, it works but it should be out of the boundary, although ::after exists in DOM, nothing is displayed.
- body::before - before all content of body
- body::after - after all content of body
So, as a cross browser solution, to apply filter to body, body::before
is sensible according to support of pseudo element across different browsers.
body::before {
/* positioning */
content: ' ';
height: 100%;
width: 100%;
position: fixed;
left: 0;
right: 0;
z-index: -1;
background-image: url(https://cdn.pixabay.com/photo/2020/04/03/15/27/flower-meadow-4999277_1280.jpg);
background-size: cover;
background-repeat: no-repeat;
filter: grayscale(1);
}
Related posts:
about not working in body tag, it may be a bug because it behave inconsistently across different browsers.
Situation 4 - Apply filter to elements other than html and body
It works without issues.
#content {
background-image: url(https://cdn.pixabay.com/photo/2020/04/03/15/27/flower-meadow-4999277_1280.jpg);
background-size: cover;
background-repeat: no-repeat;
filter: grayscale(1);
}
body, html, #content {
height: 100%;
}
<div id="content"></div>
Appendix
CSS Filter Functions
How to apply post 1
Apply to partial element post 1