简体   繁体   English

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

[英]CSS filter:invert not working with background-color

I have the following CSS applied to the <html> tag: filter: invert(1);我将以下 CSS 应用于<html>标签: filter: invert(1);

All elements get inverted even background-color of elements, (Chrome v80)所有元素都被反转,甚至元素的background-color ,(Chrome v80)

Once I try the same on Safari iOS 13 / Safari MacOS, every element get inverted except for <html>'s background-color一旦我在 Safari iOS 13 / Safari MacOS 上尝试相同的操作,除 <html> 的background-color外,每个元素都会反转

CSS filter property is supported for all browsers I'm running:我正在运行的所有浏览器都支持 CSS 过滤器属性:

https://caniuse.com/#feat=mdn-css_properties_filter . https://caniuse.com/#feat=mdn-css_properties_filter

Could someone explain this behavior?有人可以解释这种行为吗?

 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>

TL;DR : Don't mess too much with html element. TL;DR :不要过多地使用html元素。

The easy workaround is to block body 's background propagation to the document's canvas, but make it take the same size as the html by removing its margin, and applying all the styles you had on html on the body, and the ones you had on the body to a wrapper <div> . The easy workaround is to block body 's background propagation to the document's canvas, but make it take the same size as the html by removing its margin, and applying all the styles you had on html on the body, and the ones you had on 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>


More in depth observations:更深入的观察:

There are a few concepts at play here, and their interaction is not that easy to grasp (at least to me...).这里有一些概念在起作用,它们的交互并不是那么容易掌握(至少对我来说......)。

  • "Rendering Layers": When painting a page there will generally be several layers of rendering, possibly nested on which effects like filters or opacity will be applied. “渲染层”:绘制页面时,通常会有几层渲染,可能嵌套在其中应用过滤器或不透明度等效果。 The specs only define "stacking contexts", for our case here after they are the same thing.规范仅定义“堆叠上下文”,对于我们这里的情况,它们是相同的。
  • "Document's canvas" : Each document has a background canvas, which is not present in the DOM and which stands as the deepest "rendering layer". “文档画布” :每个文档都有一个背景 canvas,它不存在于 DOM 中,它是最深的“渲染层”。
  • "Background propagation" : Some special elements have special behaviors regarding their CSS background property.“背景传播” :一些特殊元素在其 CSS background属性方面具有特殊行为。 Notably, html and body may give their own background to the "document's canvas".值得注意的是, htmlbody可能会为“文档的画布”提供自己的背景。 The basic workflow is基本工作流程是

    • if html 's background is not none and not transparent , use that for "document's canvas".如果html的背景不是nonetransparent ,则将其用于“文档画布”。
    • else if body 's background is not none and not transparent , use that for "document's canvas".否则,如果body的背景不是none且不是transparent ,则将其用于“文档的画布”。
    • else do whatever you want (usually browsers render white solid color).否则做任何你想做的事情(通常浏览器呈现白色纯色)。
  • "Post-Processing" effects like filter and opacity should apply on a whole "rendering layer" when all its inner content already has been rendered.当所有内部内容已经被渲染时, filteropacity等“后处理”效果应该应用于整个“渲染层”。

  • Setting such "Post-Processing` effects on an element should isolate that element and create a new "rendering layer" from it.在元素上设置此类“后处理”效果应该隔离该元素并从中创建一个新的“渲染层”。

Now, it's very unclear how the "document's canvas" should be affected by these "post-processing" effects, and I couldn't find any definitive answer to this case in the specs.现在,还不清楚“文档的画布”应该如何受到这些“后处理”效果的影响,而且我在规范中找不到任何明确的答案。

What's for sure, is that we have [Compat] issues in there...可以肯定的是,我们有 [Compat] 问题...

Not only not all browsers do follow the same rules, but some browsers will behave differently when the page is presented as a standalone window, or in an iframe.不仅并非所有浏览器都遵循相同的规则,而且当页面呈现为独立的 window 或 iframe 时,某些浏览器的行为也会有所不同。

Since the test results do vary between windowed and framed renderings, and that StackSnippet only allows framed rendering, I am forced to outsource the test case in this plnkr .由于测试结果在窗口渲染和框架渲染之间确实有所不同,并且 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;
}

The results from these tests for majors browsers are:这些针对主要浏览器的测试结果如下:

When windowed : (screenshot orders, from left to right: nothing , filter , opacity , filter + opacity ).窗口化时:(屏幕截图顺序,从左到右:过滤器不透明度过滤器+不透明度)。

  • Firefox doesn't apply neither filter nor opacity to the document's canvas. Firefox 不对文档的 canvas 应用过滤器或不透明度。 火狐截图
  • Edge doesn't apply neither filter nor opacity to the document's canvas. Edge 不会对文档的 canvas 应用滤镜或不透明度。 (same as Firefox) (与火狐相同)
  • Chrome < 81 doesn't apply neither filter nor opacity to the document's canvas. Chrome < 81 不会对文档的 canvas 应用过滤器或不透明度。 (same as Firefox) (与火狐相同)
  • Chrome >= 81 applies both filter and opacity to the document's canvas. Chrome >= 81 对文档的 canvas 应用过滤器和不透明度。
    Chrome 屏幕截图
  • Safari does Safari 确实
    • apply the filter uniformly when there is no opacity set.当没有设置不透明度时,统一应用过滤器。
    • not apply the opacity on the document's canvas不要在文档的 canvas 上应用不透明度
    • create a new layer for <html> when opacity is set and applies both opacity and filter on the <html> 's background.设置不透明度时为<html>创建一个新层,并在<html>的背景上应用不透明度和过滤器。
      However it now uses <body> 's background color as the document's canvas... but let it unaffected by the filter.然而,它现在使用<body>的背景颜色作为文档的 canvas... 但让它不受过滤器的影响。
    Safari 截图

When framed : (screenshot orders, from left to right: nothing , filter , opacity , filter + opacity ).加框时:(截图顺序,从左到右:滤镜不透明度滤镜+不透明度)。

  • Firefox doesn't apply neither filter nor opacity to the document's canvas. Firefox 不对文档的 canvas 应用过滤器或不透明度。
    火狐截图
  • Edge doesn't apply neither filter nor opacity to the document's canvas. Edge 不会对文档的 canvas 应用滤镜或不透明度。 (same as Firefox) (与火狐相同)
  • Chrome (all versions) doesn't apply neither filter nor opacity to the document's canvas. Chrome(所有版本)不会对文档的 canvas 应用过滤器或不透明度。
    Chrome 屏幕截图
  • Safari does Safari 确实
    • apply the filter uniformly when there is no opacity set.当没有设置不透明度时,统一应用过滤器。
    • set the document's canvas to transparent when opacity is set, and create a new layer for <html> on which the opacity is applied.设置不透明度时,将文档的 canvas 设置为透明,并为<html>创建一个应用不透明度的新层。
    • create a new layer for <html> when opacity is set and applies both opacity and filter on the <html> 's background.设置不透明度时为<html>创建一个新层,并在<html>的背景上应用不透明度和过滤器。
      However it now sets the document's canvas transparent.但是,它现在将文档的 canvas 设置为透明。
    Safari 截图


So once again, I don't know if any result here is per specs, what I know is that as web-authors, we should avoid messing with it when possible.所以再一次,我不知道这里的任何结果是否符合规范,我知道作为网络作者,我们应该尽可能避免弄乱它。


Post-scriptum:后记:

  • Here is the Chromium issue from which the new Chrome behavior was introduced.这是引入新 Chrome 行为的Chromium 问题
  • Here is a proposal to allow web authors to define the document's canvas background as transparent for some devices.这是允许 web 作者将文档的 canvas 背景定义为对某些设备透明的提议

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM