I have the following CSS applied to the <html>
tag: filter: invert(1);
All elements get inverted even background-color
of elements, (Chrome v80)
Once I try the same on Safari iOS 13 / Safari MacOS, every element get inverted except for <html>'s background-color
CSS filter property is supported for all browsers I'm running:
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>
html
element.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>
.
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>
There are a few concepts at play here, and their interaction is not that easy to grasp (at least to me...).
"Background propagation": Some special elements have special behaviors regarding their CSS background
property. Notably, html
and body
may give their own background to the "document's canvas". The basic workflow is
html
's background is not none
and not transparent
, use that for "document's canvas".body
's background is not none
and not transparent
, use that for "document's canvas"."Post-Processing" effects like filter
and opacity
should apply on a whole "rendering layer" when all its inner content already has been rendered.
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...
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.
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.
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).
<html>
when opacity is set and applies both opacity and filter on the <html>
's background.<body>
's background color as the document's canvas... but let it unaffected by the filter.When framed: (screenshot orders, from left to right: nothing, filter, opacity, filter + opacity).
<html>
on which the opacity is applied.<html>
when opacity is set and applies both opacity and filter on the <html>
's background.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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With