CSS 过滤器:反转不适用于背景颜色

T. *_*Ali 5 html css sass

我将以下 CSS 应用于<html>标签:filter: invert(1);

所有元素甚至元素都被反转background-color,(Chrome v80)

一旦我在 Safari iOS 13 / Safari MacOS 上尝试相同的方法,除了 <html> 之外的每个元素都会被反转 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;
}
Run Code Online (Sandbox Code Playgroud)
<div class="text">
  If it works: color should not be red, background should not be blue
</div>
Run Code Online (Sandbox Code Playgroud)

Kai*_*ido 6

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


更深入的观察:

这里有一些概念在起作用,它们之间的相互作用并不那么容易掌握(至少对我来说......)。

  • “渲染层”:在绘制页面时,通常会有几层渲染,可能嵌套在将应用过滤器或不透明度等效果上。规范仅定义了“堆叠上下文”,对于我们这里的情况,它们是相同的。
  • “文档的画布”:每个文档都有一个背景画布,它不存在于 DOM 中,是最深的“渲染层”。
  • “背景传播”:一些特殊元素在其 CSSbackground属性方面具有特殊行为。值得注意的是,html并且body可以为“文档的画布”提供自己的背景。基本工作流程是

    • 如果html的背景不是none,则将transparent其用于“文档画布”。
    • 否则,如果body的背景不是none,则将transparent其用于“文档画布”。
    • 否则做任何你想做的事情(通常浏览器呈现白色纯色)。
  • “后处理”效果就像filter并且opacity应该应用于整个“渲染层”,当它的所有内部内容都已经被渲染时。

  • 在元素上设置这样的“后处理”效果应该隔离该元素并从中创建一个新的“渲染层”。

现在,“文档的画布”应该如何受到这些“后处理”效果的影响非常不清楚,而且我在规范中找不到任何关于这种情况的明确答案。

可以肯定的是,我们在那里有 [Compat] 问题......

不仅并非所有浏览器都遵循相同的规则,而且当页面作为独立窗口或 iframe 呈现时,某些浏览器的行为会有所不同。

由于窗口和框架渲染之间的测试结果确实有所不同,并且 StackSnippet 只允许框架渲染,因此我被迫将这个 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;
}
Run Code Online (Sandbox Code Playgroud)

这些主要浏览器的测试结果是:

窗口化时:(截图顺序,从左到右:nothing , filter , opacity , filter + opacity)。

  • Firefox 既不会对文档的画布应用过滤器,也不会应用不透明度。 火狐截图
  • Edge 不会对文档的画布应用过滤器或不透明度。(和火狐一样)
  • Chrome < 81 不会对文档的画布应用过滤器或不透明度。(和火狐一样)
  • Chrome >= 81 将过滤器和不透明度应用于文档的画布。
    Chrome 屏幕截图
  • Safari 可以
    • 当没有设置不透明度时,均匀地应用过滤器。
    • 不在文档画布上应用不透明度
    • <html>在设置不透明度时创建一个新图层,并在<html>背景上应用不透明度和过滤器。
      然而,它现在使用<body>的背景颜色作为文档的画布......但让它不受过滤器的影响。
    Safari 截图

装帧时:(截图顺序,从左到右:nothing , filter , opacity , filter + opacity)。

  • Firefox 既不会对文档的画布应用过滤器,也不会应用不透明度。
    火狐截图
  • Edge 不会对文档的画布应用过滤器或不透明度。(和火狐一样)
  • Chrome(所有版本)既不会对文档的画布应用过滤器,也不会应用不透明度。
    Chrome 屏幕截图
  • Safari 可以
    • 当没有设置不透明度时,均匀地应用过滤器。
    • 设置不透明度时将文档的画布设置为透明,并创建一个<html>应用不透明度的新图层。
    • <html>在设置不透明度时创建一个新图层,并在<html>背景上应用不透明度和过滤器。
      但是,它现在将文档的画布设置为透明。
    Safari 截图


所以再一次,我不知道这里是否有任何结果符合规范,我知道作为网络作者,我们应该尽可能避免弄乱它。


后记:

  • 这是引入新 Chrome 行为的Chromium 问题
  • 这是一个允许网络作者将文档的画布背景定义为对某些设备透明的建议。