使用 CSS 滤镜将站点置灰以及把如何排除图片

因为长者的逝世,最近不断有同学在问:应该怎么做站点置灰(去色)的需求。一般来说我都会转发张鑫旭大佬的 《小tip: 使用CSS将图片转换成黑白(灰色、置灰)》 这篇文章给对方,文章内详细的描述了应该如何处理。
虽然 filter 属性还是草案阶段,但是几乎所有的现代浏览器都有很好支持,所以可以直接使用 html{filter: grayscale(100%)} 来实现这个需求。

但是今天在社区里面看到有人提到了这样的一个问题请教css网站置灰,排除图片的问题?,需求是使用 filter: grayscale(100%) 使全站置灰之后,如何排除网站中的图片的置灰。

一开始我认为这个需求有一些点不合理,随即答复了可以按照区块去实现置灰,如果要实现这样的需求需要通过遍历来实现,并让他去和PM沟通,具体为什么要实现这样的方式。
但是后来有人补充了通过 :not() + :has() 伪类选择器实现的方式,但是还是有一定兼容性问题的。FireFox 还未支持 :has() 伪类选择器_2022年12月)


其实就是通过我说的遍历匹配所有的元素,只是他通过了 :not(:has 去匹配了所有后代不包含 img 元素的所有元素。
只不过 :has() 我只是粗略的看了一下张大佬早些时候些的相关文章,还不知道可以去搭配 :not() 来实现这样的效果。果然CSS需要脑洞大开啊,未来可能单独去写以下 :has():not() 两个伪类选择器的笔记。

好了废话不多说,直接贴上来实现的代码:

:not(:has(img)):not(img) {
  filter: grayscale(1);
}

所以其实不只是图片元素,其它的 canvasvideo 元素也是可以的是使用这样的方法的。

你们也可以通过点击下方的这写按钮来体验效果。

预览图

这个效果我是通过 jQuery 来动态给 html 元素添加了一个CSS类名,CSS的代码是这样的:

// 全部置灰
.gray-filter {
  filter: grayscale(1);
}
// 排除图片元素之外全部置灰
.gray-filter-exclude-img :not(:has(img)):not(img) {
  filter: grayscale(1);
}

✍ 尾声

下班之后在家里补完这篇文章的时候,发现了张大佬已经把这个如何实现除了图片以外都置灰的处理方法补充上来了。看了一下回复的时间,应该当初在思否问答贴内回复这个方法的人也是从这里看到的,我看描述的文案都是一样的。

好了,希望可以帮助到一些需要的同学。

相关阅读

filter - CSS: Cascading Style Sheets | MDN
:has() - CSS: Cascading Style Sheets | MDN
:not() - CSS: Cascading Style Sheets | MDN
CSS Filter Effects | Can I use
:has() CSS relational pseudo-class | Can I use

请教css网站置灰,排除图片的问题? - SegmentFault 思否
小tip: 使用CSS将图片转换成黑白(灰色、置灰) « 张鑫旭-鑫空间-鑫生活
来了,来了,CSS :has()伪类她来了 « 张鑫旭-鑫空间-鑫生活