CSS过滤器:反转不适用于背景色
Posted
技术标签:
【中文标题】CSS过滤器:反转不适用于背景色【英文标题】:CSS filter:invert not working with background-color 【发布时间】:2020-07-29 11:16:04 【问题描述】:我将以下 CSS 应用于 <html>
标签:filter: invert(1);
即使background-color
的元素,所有元素都会反转,(Chrome v80)
一旦我在 Safari ios 13 / Safari MacOS 上尝试相同的操作,除了 的 background-color
我正在运行的所有浏览器都支持 CSS 过滤器属性:
https://caniuse.com/#feat=mdn-css_properties_filter。
有人能解释一下这种行为吗?
html
filter: invert(1);
/* this background-color does not change on ios+other browsers */
background: #fff;
padding: 50px;
body
background-color: #0000ff;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
.text
text-align: center;
color: red;
<div class="text">
If it works: color should not be red, background should not be blue
</div>
【问题讨论】:
尝试添加htmlbackground:#fff
@TemaniAfif 我已经更新了 sn-p,同样的问题没有倒过来。
很有趣,same discrepancy happens with opacity
+ background-color
,FF 不会让不透明度影响 html 的背景,而 Chrome 在 iframe 中不会影响,但在页面在自己的窗口中运行时默认为白色。并且 Safari 具有 Chrome 的逆行为(这似乎更符合 IMM 逻辑)。 @TemaniAfif 知道规范对此有什么看法吗?
为什么不用:root
这个用js切换背景呢?如果我没记错的话,这通常就是现在创建黑暗主题等的方式。
是的。但我正在考虑应用实际的颜色反转应用
【参考方案1】:
TL;DR:不要过多地使用 html
元素。
简单的解决方法是阻止body
的背景传播到文档的画布,但通过删除其边距并应用您在html
上的所有样式,使其大小与html
相同身体,以及你在body
上的那些到包装器<div>
。
html
/* block body's background propagation */
background: #FFF;
/* move all one layer down */
body
filter: invert(1);
background: #fff;
padding: 50px;
/* make it cover the full canvas */
margin: 0;
.wrapper
background-color: #0000ff;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
.text
text-align: center;
color: red;
<div class="wrapper">
<div class="text">
If it works: color should not be red, background should not be blue and border should not be white
</div>
</div>
更深入的观察:
这里有几个概念在起作用,它们之间的交互并不是那么容易掌握(至少对我来说......)。
“渲染层”:绘制页面时,通常会有多个渲染层,可能嵌套在其中应用过滤器或不透明度等效果。规范仅定义“堆叠上下文”,对于我们这里的情况,它们是相同的。 "Document's canvas":每个文档都有一个背景画布,它不存在于 DOM 中,它是最深的“渲染层”。"Background propagation":一些特殊元素的 CSS background
属性具有特殊行为。值得注意的是,html
和body
可以为“文档的画布”提供自己的背景。基本工作流程是
html
的背景不是none
而不是transparent
,则将其用于“文档画布”。
否则,如果body
的背景不是none
而不是transparent
,则将其用于“文档画布”。
其他任何你想做的事情(通常浏览器呈现白色纯色)。
“后处理”效果如 filter
和 opacity
应该在其所有内部内容都已渲染后应用于整个“渲染层”。
现在,“文档的画布”应该如何受到这些“后处理”效果的影响还不清楚,而且我在规范中找不到任何明确的答案。
可以肯定的是,我们存在 [Compat] 问题...
不仅并非所有浏览器都遵循相同的规则,而且当页面作为独立窗口或 iframe 呈现时,某些浏览器的行为也会有所不同。
由于测试结果在窗口渲染和框架渲染之间确实存在差异,并且 StackSnippet 只允许框架渲染,我不得不将测试用例外包给 this plnkr。
html
background: red;
height: 50vh;
border: 10px solid green;
.opacity
opacity: 0.5;
.filter
filter: invert(1);
body
background: yellow;
margin: 10vh;
border: 2px solid green;
这些针对主流浏览器的测试结果如下:
窗口化时:(屏幕截图顺序,从左到右:nothing、filter、opacity、过滤器+不透明度)。
Firefox 不会对文档的画布应用过滤器或不透明度。 Edge 不会对文档的画布应用滤镜或不透明度。 (与 Firefox 相同) Chrome Chrome >= 81 对文档的画布应用过滤器和不透明度。 Safari 可以 在没有设置不透明度时统一应用滤镜。 不在文档的画布上应用不透明度 在设置不透明度时为<html>
创建一个新图层,并在<html>
的背景上应用不透明度和过滤器。
然而,它现在使用<body>
的背景颜色作为文档的画布......但让它不受过滤器的影响。
加框时:(截图顺序,从左到右:nothing、filter、opacity、过滤器+不透明度)。
Firefox 不会对文档的画布应用过滤器或不透明度。 Edge 不会对文档的画布应用滤镜或不透明度。 (与 Firefox 相同) Chrome(所有版本)不会对文档的画布应用过滤器或不透明度。 Safari 可以 在没有设置不透明度时统一应用滤镜。 在设置不透明度时将文档的画布设置为透明,并为<html>
创建一个应用不透明度的新图层。
在设置不透明度时为<html>
创建一个新图层,并在<html>
的背景上应用不透明度和过滤器。但是它现在将文档的画布设置为透明。
再说一次,我不知道这里的结果是否符合规范,我知道作为网络作者,我们应该尽可能避免弄乱它。
后记:
这是引入新 Chrome 行为的 Chromium issue。 a proposal 允许网络作者将文档的画布背景定义为对某些设备透明。【讨论】:
以上是关于CSS过滤器:反转不适用于背景色的主要内容,如果未能解决你的问题,请参考以下文章
过滤器:模糊(1px);不适用于 Firefox、Internet Explorer 和 Opera