New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[filter-effects-1] What is the visual effect of filter() on the document element? #282
Comments
Also need to consider: Is the filter applied before or after the UA renders its default view background color? |
I would expect a filter on the root element to affect the canvas, just like a transform on the root element is expected to affect the background canvas. From the transforms spec (end of the linked section):
However, a modified version of your test shows that browsers don't actually implement that part of the Transforms spec: WebKit and Chrome transform the background, but don't fill in extra background image repeats, while Firefox and Edge don't transform the root background at all. So, for implementers, these should probably be fixed together. But in both cases, we probably need spec clarifications, and actual normative text (not just the informative note from Transforms). Aside: For authors, a workaround that should work for now is to put the background on the |
As per #11 (comment) the filter should apply to the document element's background color. However, that comment does not mention how the default background color should be treated. For consistency with |
I think issue #11 is about containing block side effects. This is about the visual rendering, which is different. |
I agree with @mstange - I think the filter should apply to the canvas, but not the default backdrop color. So in the @smfr's first example ( |
Informal twitter poll here: https://twitter.com/smfr/status/990792916124581888 |
Does CSS specify anywhere what the default background is? Is it as if the UA stylesheet had |
The default background is traditionally customizable (e.g., Firefox lets you set this as a user style). CSS Backgrounds says:
However, WHATWG HTML says:
Elsewhere, CSS Backgrounds says that a background on the root element or HTML body element is propagated to the canvas. So it is theoretically possible to insist that "the background that shows through from a transparent canvas" is white, while also allowing customization in the form of a Firefox implements it using the layered approach: the user-defined color is applied underneath any background set on the root element. |
There's a difference between "the background that gets propagated to the canvas" (from If filters on Obviously, there's some background that isn't affected by the filter, so that you can show something underneath an opacity() filter. Rather than inventing yet another layer to explain this, let's just be consistent with previous resolutions (such as our resolution that |
(And note that, as a result of that thread, Color now mandates that the root element's default background is |
Rik points to previous discussion at https://lists.w3.org/Archives/Public/public-fx/2015JanMar/0052.html |
Sadly twitter mostly disagrees with the previous resolution about how filter() on the root works; most people expect |
@smfr The thread comes to the same conclusion as @tabatkins’s proposal above and does make sense IMO. I agree with the conclusion that some kind of backdrop is required for compositing which should not be affected by filters either. (Though might be relevant for feBlend of course.) With defining Though the voting on the Twitter thread might go in another direction, the outcome in the thread makes the most sense IMO. |
I agree with @tabatkins's points. It's good to have a solid background compositing base on top of which |
Here's another thing with the Firefox/Blink implementation: Now add a background on the html: |
So how does the resolution work in the case of: |
It gets propagated to the canvas, and is not affected by filters on the The behavior in the two previous examples is unfortunate but similar things happen in lots of other circumstances. For example, in |
Yeah, the propagation from |
Another informal twitter poll with convenient stats: https://twitter.com/LeaVerou/status/1001859421469855744 |
Again, these sorts of polls aren't particularly useful. This isn't something people have thought about before, so you're just getting a kneejerk response, and the phrasing of the question ("turn the default white background black") misleads the intuition, too - it sounds like you're saying the element has a white background by default, and so the two code examples are equivalent (just that the first omits a background and so gets the default white), when actually the two examples give the element totally different background declarations. Sure, getting people's quick intuitions can be useful, but those intuitions can also be inconsistent, and it's better for everyone to have a consistent, rational platform even if occasionally corner cases require an "oh, I get it" moment. If nothing else, changing it to ask about |
@tabatkins I just copied @smfr's wording. If you have a better wording to suggest that fits in 280 characters, please let me know and I'll post that :) |
@LeaVerou The problem are the details described in #282 (comment) @tabatkins correct me if I am wrong but we had this discussion especially because of @mstange I agree that we need to be compatible with |
Yup, exactly, |
Update to the discussion about canvas background colors: apparently Safari under the new OSX dark mode is using a near-black canvas. (from https://twitter.com/stanton/status/1003971450804555776, and confirmed by various other Twitterers) |
Amelia, that's a bug in Safari and is not intentional. |
Proposal: specify in terms of: In this model, filters only affect the page background if it's set by the author. Alternatively, if we specify that the intermediate layer by default has the same color as the bottom layer, then the UA-default background would get affected by filters. |
Following-up on the blend-modes issue: I'm working with this CodePen testcase: As anticipated on the call, every browser does this differently currently:
As Tab noted, there was a resolution from 2014 to agree with @cabanier's proposal here. That is specifically about But, since the current state is horribly inconsistent, the good news is that changing the spec (to make the colour of the UA-supplied canvas layer propagate to the author-controlled canvas layer if that layer has no author-supplied images or colors) probably won't have any negative web compat effects! Making that change would mean that, for this specific test case (an author-supplied partially transparent root background image), you would blend with or filter the partially transparent layer and then composite over the "untouchable" UA-supplied canvas. (And whatever gets decided here, we definitely need clarifying edits to Compositing and Blending, to match. And Backgrounds, for that matter.) |
Here is a complete proposal that I think will satisfy the use-cases and is rational: https://docs.google.com/document/d/1iN0LiaKPF3NZ2PCXD9gdWz1WmruhQIER8fJ_EYMm5YE/edit# In particular, it will paint the examples given by @smfr the way developers seem to expect. Also, filters will paint after scrolling, which resolves the main issue left in #11. |
The proposal sounds great to me. The only thing I'm unsure about is the two mentions of "white" in the Drawing algorithm section. Should both of those be the UI-supplied default background color? |
I wasn't sure why the |
I used white for two reasons:
Given that filters can have opacity effects which mix with the UA background color, under this proposal, I also think we should consider just specifying that the UA background color must be white. Though I don't know all the history of use cases this might be defeating. Chrome certainly doesn't allow anything other than white, even when there is an installed theme with another color background. |
The Compositing and Blending spec says that the backdrop color is white. I don't know how normative that is, but you may need to change it.
The spec also says that the order of graphical operations is:
This new proposal seems to change the order to blending, filtering and compositing for the root element. How are clipping and masking affected by this change? |
This is fine, we can follow that order. The important thing is to apply after the overflow clip and Though I'm not sure if masking or css clip can apply to the root element at all. |
The CSS Working Group just discussed The full IRC log of that discussion<dael> Topic: What is the visual effect of filter() on the document element?<dael> github: https://github.com//issues/282#issuecomment-418954332 <dael> chrishtr: In previous WG meeting we discussed a couple of issues. One was filter is a containing block for all elements unless filter is on root. Reason for that is that it's important for impl reason and rationality of platform for it to be CB. For root we want fixed to behave correct <dael> chrishtr: Second issue from smfr is that it's unclear what happens when you put a filter and what happens to default white backdrop <dael> chrishtr: Discussed and had somewhat resolution similar to my proposal, but needed use cases <astearns> https://docs.google.com/document/d/1iN0LiaKPF3NZ2PCXD9gdWz1WmruhQIER8fJ_EYMm5YE/edit# <dael> chrishtr: THere's 3 drawing layers for every doc. UA background layer, canvas layer, root element layer. Blended for final output <dael> chrishtr: Want to make sure final is opaque. That's function of UA background <dael> Rossen_: Always meaning per discression of UA right? <dael> chrishtr: yes but don't think it's good idea <dael> Rossen_: If a UA wants blending enabled for, say, webview with different composition other then opaque they should be allowed. Saying background is always opaque is too strong <dael> chrishtr: Would you agree it's important for dev not to be able to cause blending there? <dael> Rossen_: Agree. Trying to distinguish that UA layer is controlled by UA only. Opque or not is per discretion of UA. Rest is correct <dael> chrishtr: Canvas layer is second. Purpose is a blending backdrop for root element. Root element never has a background, lawyas stolen by canvas layer. THat's as is. Other cases in HTML where body gets its background sotlen, but that's not valid here <dael> chrishtr: I want mixed blend mode and filter to apply to canvas layer as it mixed blend and filter of root element and canvas. Default color of canvas is white. If you don't spec a color on html element canvas will be white <dael> Rossen_: Purpose of root element layer? <dael> chrishtr: Content that's not the background but drawn into stacking context. If you have a non-stacking div that's filtered in <dael> Rossen_: Makes sense <dbaron> http://software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Cstyle%3E%0Abody%20%7B%20background%3A%20aqua%20%7D%0A%3C%2Fstyle%3E%0A%3Ciframe%20srcdoc%3D%22%3Cdiv%20style%3Dbackground%3Ablue%3Bheight%3A30px%3E%3C%2Fdiv%3E%22%3E <dael> smfr: There was a step to prop. the UA background layer color to the canvas. If you make canvas whit eyou prevent UA from transparency. <dael> chrishtr: Default color of the canvas is white. Step 1 in the algo is paint white into UA. step 2 is put background of root into canvas and if no background put white. Guar. of opaque comes from UA layer, not canvas. UA layer forces the opaque, not canvas. <dael> dbaron: Question on assumption. I put a test case in^ <dael> dbaron: Only tested FF, but iframe is transparent. Canvas does not always have white background <dael> chrishtr: I think the demo is in case of iframe...yeah...white background is root frame but not sub frames. Right. And iframes can be transparent. Right. <dael> astearns: Should that be added to algo? <dael> chrishtr: Yeah. White color is specific to root document. For subframes it's transparent <dael> chrishtr: Tranparent iframe is legitimate <dael> Rossen_: There is no ua background layer in this case <dael> chrishtr: THere is eventually if you go up stacking <dael> Rossen_: Yes, for the frame itself <dael> chrishtr: Right. And as dbaron said it doesn't draw white by default. There is no infinite canvas for an iframe. That needs to be thought through <dael> chrishtr: Another comment on github from earlier today that asked about clipping and masking order relative to filter and blend. Compositing says filter first and then...there's an order <chris> yes, filter should be applied first. <chris> so there are two separate clip stages? <dael> chrishtr: Clipping is clip-path. I think it's important to be after scrolling and overflow clip. Not masking or clip-path. Not sure you can mask or clip-path root. Does anyone know? <dael> chrishtr: It would apply to iframes but not root document <dael> Rossen_: QUestion was? <dael> chrishtr: Masking for css clip to the root <dael> chrishtr: Any way to cause clip on root element <dael> chrishtr: Not sure it makes any sense for root of webpage or if UA impl. Makes sense for an iframe <dael> Rossen_: NOt sure <dael> Rossen_: Assume the use case for iframe I would question why that use case doesn't apply to top level root <dael> chrishtr: Reason wuld be iframes are in a larger drawing serface. <dael> Rossen_: Yes, unless root is inside an iframe. If use case applies to doc in iframe, why when it's not. <dael> fremy: Also if you're drawing on a glass screen I can imagine websites wanting to be transparent and only white background when they want it. I don't think there's a reason to think iframe use case doesn't apply on root <dael> chrishtr: Okay. I see. <dael> Rossen_: Where do we go? Your summary in the explainer is decent. What's next? <dael> chrishtr: Need to go into more detail about iframes and clipping/masking. Then I think it'll be ready to come back <dael> Rossen_: This is great chrishtr . Thank you for putting this together. |
I don't think saying that it composites against opaque white is any simpler than saying it just does against "the backdrop", with a definition that the backdrop is whatever the UA wants it to be (typically transparent for iframes and opaque white for root-level documents, but can be anything). Given that all you're doing with it is compositing over it, the identity of it doesn't matter, and being unnecessarily specific makes it harder to read when you actually know the details. ^_^ |
For SVG filters on the documentElement we probably also need to define the rectangle that should be used for the filtered element's BBox. I think it would make the most sense to define it to be the viewport rectangle, and not the scrolled size of the document. So the following testcase should have a blue fill in the lower half of the viewport at all scroll positions: <!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>The filter should not scroll with the root scroll frame, and the lower half of the viewport should be blue.</title>
<style>
html { filter: url(#filter); }
body { margin: 0; height: 4000px; }
</style>
<body>
<svg height="0">
<filter id="filter">
<feFlood flood-color="blue" x="0%" y="50%" width="100%" height="50%" result="blue"/>
<feMerge>
<feMergeNode in="SourceGraphic"/>
<feMergeNode in="blue"/>
</feMerge>
</filter>
</svg>
<script>
document.documentElement.scrollTop = 800;
</script> |
I have updated the proposal to take into account feedback from last time. The new proposal treats the root element like any other stacking context, except that:
Details and testcases: To answer two anticipated questions related to discussion: Q: Why is there still a solid white layer for the root element of the root document? Q: (from prior WG discussion) Do iframes support clipping? |
The CSS Working Group just discussed
The full IRC log of that discussion<gregwhitworth> Topic: Next on graphics issues<gregwhitworth> Rossen: this is about success on filters elements on the root element <Rossen> github: https://github.com//issues/282 <gregwhitworth> chrishtr: I brought this a few months ago - there were a few pieces of feedback <gregwhitworth> chrishtr: how do you treat the root element, in particalur frames that are transparent - similiar to iframes <gregwhitworth> chrishtr: it's in a webview in side of an app for example <gregwhitworth> chrishtr: some other device that wants transparency <gregwhitworth> chrishtr: I did some more testcases <gregwhitworth> chrishtr: and have a proposed solution <gregwhitworth> chrishtr: the new proposal is that - there are two conceptual layers you draw into, the frame root background layer <gregwhitworth> chrishtr: the root element layer <gregwhitworth> chrishtr: the background is always opaque white <gregwhitworth> chrishtr: so there is white and then the root element <gregwhitworth> chrishtr: you draw the stacking context of the root element into that layer except the background is extended into the infinite canvas <gregwhitworth> chrishtr: everything would apply as is <gregwhitworth> chrishtr: clipping and filter and blend-mode and backdrop-filter are done in the same order as before <gregwhitworth> chrishtr: so I went throught he examples that simone fraser came out as he expected <gregwhitworth> mstange: I don't think that is true <gregwhitworth> mstange: in your root element layer there is no white background <gregwhitworth> mstange: if you don't have a background element on html then you can apply and filter and it will break <gregwhitworth> mstange: if you have the background there then we will get what Simon expects <gregwhitworth> mstange: we need to update background-blend mode or we cannot invert <gregwhitworth> krit: blend mode currently defines white to be the pages backdrop <gregwhitworth> mstange: yes it does, but only the result of the blending is composited on top of it - it doesn't participate <gregwhitworth> chrishtr: is the contention - if you make it part of it then it fixes the invert, but if you don't then it breaks it <gregwhitworth> mstange: if you make the white part - part of the page group you fix invert but change how mix-blend-mode is defined <gregwhitworth> mstange: this part isn't implemented by Chrome <gregwhitworth> mstange: correct? <gregwhitworth> chrishtr: I think Chrome is probably incorrect <gregwhitworth> mstange: but if we change it, Chrome doesn't need to change <gregwhitworth> chrishtr: true <gregwhitworth> krit: I want to change web pages that will always have the white backdrop <gregwhitworth> krit: it is there for sites that didn't provide a background, is it providing the background for websites <gregwhitworth> mstange: we still allow people to change the default color to the background <gregwhitworth> mstange: there may be a11y issues here <gregwhitworth> chrishtr: let's save that for a different issue <gregwhitworth> mstange: sure <gregwhitworth> chrishtr: do we want to consider white as part of the root <gregwhitworth> chrishtr: then the root is not different than any other stacking context <gregwhitworth> mstange: the filter may be opacity: 0 - you'll need some type of result <gregwhitworth> mstange: I support painting the background twice, once inside and outside of the page group <gregwhitworth> mstange: and defining the remaining issues <gregwhitworth> chrishtr: why twice <gregwhitworth> chrishtr: why isn't it ok to composite the filter to white? <gregwhitworth> mstange: that could work <gregwhitworth> chrishtr: you should just expect it to be composited to white <gregwhitworth> mstange: if we say it's white for now <gregwhitworth> mstange: if you want invert to be inverted <gregwhitworth> mstange: it needs to be painted in the page group <gregwhitworth> mstange: if you want a merge to apply to the default background color <gregwhitworth> mstange: the white needs to be present to the input of the filter, now you have a result so you composite that to something, what is under the result <gregwhitworth> chrishtr: it is white <gregwhitworth> mstange: that's why it needs to be twice <gregwhitworth> chrishtr: in the scenario where there is no background defined <gregwhitworth> Sim: you propogate the color to the root element layer, and then do the composition <gregwhitworth> chrishtr: yes <gregwhitworth> chrishtr: I think it's equivolent <gregwhitworth> simon: if the root is white with alpha <gregwhitworth> chrishtr: I think the math comes out the same <gregwhitworth> krit: depens on the transform and color <gregwhitworth> krit: let's say you can set the color in the page group, what would happen? Would backdrop not get inverted? <gregwhitworth> mstange: FF settings don't allow alpha, the result would be opaque and that would be composted onto white, always gives you the same result <gregwhitworth> krit: my only concern - do we always have a solid color <gregwhitworth> mstange: as written, it would allow support for any background color including no background color besides what is defined on the root background color <gregwhitworth> chrishtr: whatever the screen happened to have on it would be composited <mstange> proposed resolution: In mix-blend-mode, reword the paragraphs "The page group is an isolated group. The page group is composited with a backdrop color of white with 100% opacity." to mention that the default background color is also painted within the page group, i.e. that blending happens with the default background color. <gregwhitworth> Rossen: Any objections? <gregwhitworth> Resolved ^ <gregwhitworth> Proposed Resolution: the filter applies to the result of the page group on top of the root background color <gregwhitworth> Rossen: objections? <gregwhitworth> Resolved ^ <gregwhitworth> mstange: your document also changes opacity, mix blend modes and filter? <gregwhitworth> chrishtr: you mean it also changes opacity? <Rossen> RESOLVED: In mix-blend-mode, the default background color is also painted within the page group <gregwhitworth> mstange: if you have a background red on root and opacity: 0 <Rossen> RESOLVED: the filter applies to the result of the page group on top of the root background color <gregwhitworth> mstange: if I have background red on the root element, does this go inside the page group and root group? <gregwhitworth> chrishtr: no <gregwhitworth> mstange: that changes what occurs - this does not change the root element <gregwhitworth> chrishtr: this would change <gregwhitworth> mstange: opacity is a type of filter <gregwhitworth> mstange: clip-path and mask would change as well <gregwhitworth> mstange: if you have clip-path on the root element, the clip would effect the background of red <gregwhitworth> chrishtr: I think that's good <gregwhitworth> mstange: I agree <gregwhitworth> Proposed Resolution: opacity, clip-path, mast and clip path will be applied to output of the page group on top of the root group <gregwhitworth> mstange: I don't agree with clip-path <gregwhitworth> chrishtr: it's always a stacking context <mstange> s/clip-path/clip <gregwhitworth> mstange: should we just not mention clip <gregwhitworth> chrishtr: sounds fine <smfr> s/mast/mask/ <gregwhitworth> Proposed resolution: clip path, opacity, mask will be applied to the output of the page group on top of the root group <gregwhitworth> Rossen: objections <gregwhitworth> Resolved ^ <Rossen> RESOLVED: clip path, opacity, mask will be applied to the output of the page group on top of the root group <gregwhitworth> chrishtr: the reason I think we should use white as the background is to provide consistency to authors <gregwhitworth> chrishtr: this is inconsistent with the need for a dark mode <gregwhitworth> krit: why not just keep a weight <gregwhitworth> Simon: Why not have white be the default and allow UAs to adjust it <gregwhitworth> chrishtr: I'm fine with that <gregwhitworth> chrishtr: should we ok with defining opaque <gregwhitworth> krit: we should define the UA may define the background color and default is white <gregwhitworth> Simon: and it doesn't need to be opaque <gregwhitworth> Proposed Resolution: The background color is UA defined with default being white <gregwhitworth> Resolved: The background color is UA defined with default being white |
Next step is to apply the relevant updates to each spec based on the resolution. Then will make the change to ship the change in Chromium, file issues against other browsers and close the issue. |
I was pointed here in response to a Mozilla bug I filed, and have been reading the comments.
A kneejerk response from folks who haven't thought about this before is very useful, as it illustrates what the web developers intuitivly expect from the web platform. The platform should try to conform to this expecation where it can ("least surprise"), so it is helpful to know what that expectation is. |
Sometimes yes, sometimes no. It depends on what's being asked and how it's being asked, and what other factors aren't being mentioned. Many aspects of the web platform aren't intuitive, or have multiple possible intuitions to go by. Like I said in the very comment you're responding to:
|
WebKit and other browsers disagree about the visual rendering of filter() on the document root element:
html { filter: invert(1); background-color: blue; }
https://codepen.io/smfr/pen/LmxZZP
Safari renders white text on yellow, Blink/Firefox render white text on blue.
Should the root background be affected by the filter()? I would expect yes, making WebKit behavior correct.
The text was updated successfully, but these errors were encountered: