-
Notifications
You must be signed in to change notification settings - Fork 672
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
[cssom] [css-display] [css-values] Clarify behavior of window.getComputedStyle on detached subtrees, and the definition of "the root element". #1548
Comments
cc @bzbarsky |
Which document? The node document of the element passed to
"The document" (which one, per above), or "a document" or "a document that has a browsing context"? I'm pretty sure they compute style for an element that is in its node document's document tree if that node document has a browsing context. Dunno what they do if you |
Err, sorry. I meant Stylo (Servo's style system). Servo itself apparently returns the empty string for disconnected nodes. So in the following test-case, with <!doctype html>
<style>
div { color: yellow }
</style> and <!doctype html>
<style>
:root { font-size: 100px; }
div { color: green; }
</style>
<iframe src="./frame.html"></iframe>
<script>
let iframe = document.querySelector('iframe');
iframe.onload = function() {
let detached = document.createElement('div');
alert(iframe.contentWindow.getComputedStyle(detached).color)
alert(getComputedStyle(detached).color)
document.body.appendChild(detached);
document.body.offsetTop;
alert(iframe.contentWindow.getComputedStyle(detached).color)
alert(getComputedStyle(detached).color)
}
</script> Both Gecko and Stylo behave the same way, resolving against the document associated with the window Not sure what does Edge do, I can't test it. |
From a recent test I ran for the no browsing context case: const xdoc = xhr.responseXML;
const div = xdoc.getElementById('test');
div.style.opacity = '0';
alert(getComputedStyle(div).opacity); We get '0' in Firefox and Edge, but null in Chrome. However, if instead of using the style attribute, we set style in a |
That being said, I don't believe the real question here is the details of how things work for font-size with rem units; the real question is: Question 1
Question 2
Current results
Moving forward My personal point of view is that returning the default style is a very nice feature but, while Webkit's solution is lazy, it is also very simple to implement. We would really like Chrome to support computing styles on detached subtrees but if the Chrome team isn't interested in pursuing this, the easiest path to interop is for us to stop computing this default styles and return empty strings. I think Edge's behavior is interesting because you can use it to determine the minimum subset of inline styles you need to add to an element to create a proper copy/paste. You compute the styles of all the elements, then you clone then, get the computedStyles of the cloned root and add inline styles for anything that has changed, and continue to do so in dom order until you have processed all elements. I cannot imagine another use case for this on top of my head. Pinging @tabatkins -- what are your thoughts here? |
Which tree? With shadow DOM this is not a trivial question. Further, in all cases the "tree" involved is that of the element's node document, I assume, not of the computed style object's window's document. And in that case, again, what happens when that node document is an XHR responseXML or equivalent. |
Also, an element can be in the document tree but not be on the flat tree (#1964), like if it is an unassigned node of a shadow host. Where should you inherit from in that case? |
That makes sense to me. I have the feeling that an API like This is another reason why you don't want to apply the document's stylesheets on nodes that are currently in a detached tree, because it yields inconsistent results depending on your current realm. Edge's behavior guarantees stable results for identical detached markups in different documents since we only apply inline styles and the default style on these elements.
How does where you document comes from matter? In Edge at least, it is perfectly fine to interpret any xml document as a stylable document (xhtml by default). In fact, when you open an XML file in a tab, we render the XML file directly (though we add a script to append XHTML nodes to it so there is something more interesting to render than inline text). https://wptest.center/#/hl9yd1 (Computed styles in xml trees)
There is indeed also the question of what to do with nodes that do not have used styles. I don't think there should be special sub-categories inside that category; nodes that do not generate a box (whether it's because one of their ancestors is display:none, because they were moved into a region flow and overflowed beyond the last region box, or because they were under a web components and didn't get pulled back into its shadow tree) should return their computed style, and their computed style should follow the same rules as usual (inherit from its parent element, or host if it's a shadow root, etc...). If that is not the case right now in some browsers, I would file bugs on the browsers that don't comply with this. Everybody seems to be interoperable regarding nodes in display:none subtrees. |
An element assigned to a slot doesn't inherit from the shadow host, but from the assigned slot. There's no spec that defines that in case it's not assigned to any slot it should inherit from the host, afaict. |
Not that this is neither what the current spec says nor what browsers currently do, last I checked... So while it would be nice, it's not obvious how web-compatible it is. :(
Of course the "default" (UA + user) style can be different in different documents. For example, nothing prevents media queries in UA/user sheets. I know for a fact people use them in user sheets.
Because it may not have an attached browsing context or other machinery that might be needed to compute styles. What is the viewport size of an XHR responseXML document and why, for example? The rest of what you say about XML is not relevant to my question: my question is specifically about documents that are not "in a browsing context".
Things that are not in the flat tree don't even have a concept of computed styles, because inheritance is undefined for them. And it's not clear that they have a clearly defined concept of specified styles either.
"seems" is key. For example, Gecko and WebKit/Blink don't agree on http://jsbin.com/xiluvogequ/edit?html,output (I haven't tested Edge so far). |
Ah, that should probably be added then; more than likely it's just an oversight. Using their parent's style is the closest approximation of the behavior that would happen whenever it gets slotted, so that looks reasonable to me.
I'm fairly sure Edge is doing that, or is at least pretty close from that.
The testcase I provided shows that, at least in Edge, that does not matter. I agree that we should probably define what to do with media queries in that case. In Edge, we seem to evaluate everything as if the viewport was 0px by 0px. https://wptest.center/#/zq8ym1 (Computed styles in xml markup, with media queries)
http://jsbin.com/sitivicafo/1/edit?html,output (updated to work in Edge as we don't support srcdoc). We match Chrome and return the style you would get from applying the styles of the iframe. I will admit I'm really perplexed with Firefox's behavior here. Applying the stylesheets of one document on another document doesn't seem relevant, and seems more like a bug than a feature. |
It's what https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle explicitly requires, note.... (In the case of Firefox there's an implementation constraint that a display:none iframe doesn't have the things that are needed to compute styles at all, so we do the next-best thing, because not computing styles at all here would fail for web compat.) |
🙄 |
One slightly annoying thing of having to expose styles for elements not connected to the document is that you need to update styles for shadow roots whose host is outside of the document, which is slightly annoying. https://bugzilla.mozilla.org/show_bug.cgi?id=1449243 is an assertion failure resulting from me forgetting to do that :) |
…y default. r=bz Now that NODE_FORCE_XBL_BINDINGS is gone, the only reason OwnerDoc() was added in bug 1432490 is also gone. Let's go back to using the composed doc, at least until the CSSWG decides on what's the computed style of something that's not in[1]. [1]: w3c/csswg-drafts#1548 MozReview-Commit-ID: EV1c46kkUva --HG-- extra : rebase_source : 3cd036519b90b42cb920d8f854d530c8ced6ea9c
The Working Group just discussed
The full IRC log of that discussion<dael> Topic: Clarify behavior of window.getComputedStyle on detached subtrees, and the definition of "the root element"<dael> github: https://github.com//issues/1548 <dael> emilio: While I was doing the styling stuff it became unclear and it became obvious that each browser does something different. <dael> emilio: FF does if you go across document it's sometimes across document, sometimes the ones attached to that doc. We should decide how it should work. <dael> Rossen: In your issue it's detached sub trees. <dael> emilio: Spec says whenever you call window.getComputedStyle on a document it says you should only get values in that window. <dael> TabAtkins: I'd rather say they don't have a computedStyle. <dael> emilio: Yes, you can't do it on an iframe. If you break that the web breaks. There's 3 cases. Element outside doc, computed stylle cross document. <dael> TabAtkins: Also shadow dom. If it's detached no style. If it's in an iframe that happens to be detached we can discuss. The others have no style. <dael> TabAtkins: The flat tree case there's nothing to inherit from. <dael> rune_: But for not slotted and fallback for slotted? <dael> TabAtkins: Yeah. <dael> rune_: I don't know what is a sensible choice. <dael> TabAtkins: String param. <dael> fremy: For us it's work. Anything that's not tree I think it's reasoable to say don't render a style. All the use cases I have are internal and we don't need the API. For the API elements outside the tree can return no style. Still want it to work in documents. Spec requests if you call getComputedStyle from one window to another you have to get the values from the other window. <dael> TabAtkins: spec bug <dael> fremy: We don't want this. If we try and run this we get the wrong docuemnt. if you call getComputedStyle you get the values for the document of the element for which you called. <dael> TabAtkins: Agree. <dael> Rossen: Separate issue, though. Back to this one. What do we return on elements not part of any document? <dael> Rossen: In Edge we go threw pains to try and calc what it should have been and it's a pain. We'd rather return some stock style with initial values or not return anything. <dael> emilio: Makes sense. I think we can switch FF for non-iframes because we have archetectur that prevents us from this for iframes. <dael> TabAtkins: I'd like to know more why you think web compat on iframes <dael> emilio: blink returns style of actual document. But you can't say there's no style. <dael> dbaron: Gecko has had security bugs about getting confused about styles between doc <dael> emilio: When we know we're in the mess we're now consistant. <dael> TabAtkins: Boris mentions iframes. What's the next best thing. <dael> emilio: computing style from the window. <dael> TabAtkins Returning some styles is required for web compat. <dael> Rossen: But a stock style with initials <dael> emilio: Might not work. <dael> emilio: Still talking corss document? Detached sub trees returning no style works. <dael> TabAtkins: Detached element or one in a detached sub tree should return no computed styles <dael> rune_: Boris mentioned... <dael> Rossen: One at a time. <dael> Rossen: For elements not part of a tree or part of a detached tree they return no computed styles <dael> Rossen: Obj? <dael> RESOLVED: For elements not part of a tree or part of a detached tree they return no computed styles <dael> Rossen: next. <astearns> (and by no computed styles, we mean empty strings) <dael> TabAtkins: An element not in the flat tree <dael> emilio: Either return no style or return from the default. <dael> Rossen: Reason to do that? <dael> emilio: We don't ship shadow dom. <dael> rune_: Blink does the same. <dael> TabAtkins: Let's do it. No style. <dael> Rossen: Elements not part of a flat tree return no style for getComputedStyle <dael> emilio: You sure blink does that? <dael> rune_: Not in the flat tree you get parent value which is null. <dael> rune_: If not we should fix it. <dael> Rossen: Obj? <dael> RESOLVED: Elements not part of a flat tree return no style for getComputedStyle <dael> TabAtkins: calling gCS from one window on an element from another document should return the element's normal styles <dael> TabAtkins: If we decide later we needed it we can change. <dael> fremy: That's what we do. <dael> TabAtkins: Regardless of what window you obtain the gCS function from the origin of the style is whereever the element is <dael> Rossen: Obj? <dael> RESOLVED: Regardless of what window you obtain the gCS function from the origin of the style is where ever the element is <dael> TabAtkins: Next is a display:none or detached iframe or elements inside of it have a window they can hit and a styling context, but are not being rendered. In this case we have to return something, we can return all initial. <dael> Rossen: I think last time we tried this someone...FF or Blink...returned stock style <dael> emilio: I suspect returning stock style is not going to be web compat. jQuery used to create display:none iframe and point computed style there and it wants to know the default style for a div. <dael> fremy: I think no change. <dael> emilio: There's a question of how MQ are resolved. <dael> TabAtkins: All MQ resolve. <dael> fremy: I don't remember what we do. I don't think it matters for compat. <TabAtkins> s/resolve/are false/ <dael> smfr: I have this memory that browsers are going up the render tree for a display:none iframe. Don't ads create them? <dael> emilio: gecko doesn't do anything like that. I think blink doesn't create render trees. <dael> smfr: Yeah, we created some optimizations. <dael> ??: We've gone back and forth. We've tried to create it, but we've gone back and forth. <emilio> s/??/eae/ <dael> smfr: getComputed Style may have a [missed] <smfr> s/[missed]/created a render tree <dael> eae: WE don't do that today and haven't had a reason to revert that decision. <dael> smfr: I'm not objecting, but I thik there's compat. Long term I think we all agree. <dael> Rossen: We've held the display:none hammer for a long time. <dael> Rossen: If you guys are doing it then it should be web compat. <dael> eae: Too early to tell. <dael> Rossen: If we spec it would be that display:none iframes return nothing? <dael> eae: Yeah. <dael> emilio: iframes that are not in the document? I guess the have no style. <dael> Rossen: They shouldn't. <dael> emilio: So display:none iframes and iframes not rendered in the document. <dael> Rossen: They're elements that are not part of anything. That they're iframes doesn't make them less of an element. <dael> Rossen: I think what you raised is for the subtrees inside iframes what do we do. <dael> emilio: FF has an API that we added for jQuery. We tried to remove it and failed because calling getComputedStyle on an iframe that's not rendered. <dael> Rossen: So there is a compat issue. <dael> emilio: I suspect it's still the case. <dael> Rossen: Proposal? <dael> emilio: I'd love to say we don't return style but I don't thinkt hat's reaslistic. I think all browsers return. <dael> Rossen: We do. We go through serious pains to compute styles in all situations and we want out. If there's a compat reason for jQuery <dael> emilio: It's an old version of jQuery. <dael> Rossen: Plenty uses older jQuery, though. <dael> emilio: If someone wants to try not returning style on iframes and see what it does that would be nice. <dael> eae: I don't think we've shipped not returning styles <dael> Rossen: From behavior PoV returning none makes most sense. We can try and spec it and based on impl feedback we might come back and say compat blocks this and we need to revisit. <dael> emilio: And if we do we have to define MQs. If people are willing to try this works. <dael> Rossen: Prop: getComputedStyle returns no result for elements part of display:none or detached iframe <dael> emilio: non-rendered type iframes <dael> Rossen: Prop: getComputedStyle returns no result for elements part of non-rendered iframes <dael> RESOLVED: getComputedStyle returns none for elements part of non-rendered iframes <dael> Rossen: Anything else o nthis issue? |
…and hidden frames. This tests resolutions from w3c/csswg-drafts#1548.
getComputedStyle returns styles in the node's document per the resolution in w3c/csswg-drafts#1548.
…and hidden frames. This tests resolutions from w3c/csswg-drafts#1548.
getComputedStyle returns styles in the node's document per the resolution in w3c/csswg-drafts#1548.
…and hidden frames. This tests resolutions from w3c/csswg-drafts#1548.
getComputedStyle returns styles in the node's document per the resolution in w3c/csswg-drafts#1548.
Additional resolution in w3c#1548.
* [cssom] Make elements outside of the flat tree or detached not expose styles. Fixes w3c#1548 * [cssom] Let elements in non-rendered iframes not expose styles. Additional resolution in w3c#1548. * fixup! [cssom] Make elements outside of the flat tree or detached not expose styles. * fixup! [cssom] Let elements in non-rendered iframes not expose styles.
Consider the following test-case:
The behavior across browsers is as follows:
block
,16px
.inline
,16px
inline
,100px
.Per https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle, there isn't anything off-hand that justifies WebKit/Blink's behavior here.
Now, for the other interop problems the question is: what is the definition of "the root element"?
There are two spec sections that potentially apply here:
https://drafts.csswg.org/css-display/#transformations (1):
and https://drafts.csswg.org/css-values/#rem (2):
So the different behaviours are as follows:
Gecko takes the detached element as "the root element". For Gecko "the root element" is effectively the root of the inheritance subtree. That means that in Gecko, for example,
rem
units don't work as expected on the::backdrop
pseudo (since it inherits from nothing, and thus1rem
will always be the initial font-size).Edge seems to apply that same definition for (2), but not for (1).
Servo uses the document element of the document for both sections of the spec (which I think it's consistent, and doesn't have the problem with
::backdrop
).Blink and WebKit seem to just not compute style if the element is outside of the document, which seems wrong per https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle.
So, two questions:
Is the behavior of Blink/WebKit justified by any reasonable interpretation of the spec, or is it just a browser bug? It sounds like the second to me, but worth confirming.
What is the definition of "the root element"?
Edge's behavior seems inconsistent here, but both of the Gecko or Servo's interpretation look consistent to me.
Gecko's behavior have the inconveniency of
rem
units on::backdrop
though. I haven't checked other browser's behaviour in depth with regards torem
units and::backdrop
. From code inspection, I think Blink at least uses the document element's font-size1.The text was updated successfully, but these errors were encountered: