shadowDOM inheritance of display properties does not work for <slot> and computed styles
Reported by
d.vel...@gmail.com,
Jan 20 2017
|
||||||||
Issue description
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Steps to reproduce the problem:
This code out of content, but should be enough to describe the problem.
1. shadowDOM
<!-- CUSTOM ELEMENT -->
<div class='xItem'>
<div class='inner'>
<!-- CONTENT -->
<slot name='element'></slot>
</div>
</div>
2. CSS
.xItem {
display: flex;
flex-flow: row wrap;
flex: 1 0 auto;
}
.inner {
display: inherit;
flex-flow: inherit;
flex: inherit;
}
.element {
display: inherit;
flex-flow: inherit;
flex: inherit;
justify-content: center;
}
3. DOM
<x-item slot='element' class='element'>
content
</x-item>
What is the expected behavior?
It is expected that CSS rules go as following: .xItem -> .inner -> slot -> x-item and as the result 'content' of <x-item> should be centred.
What went wrong?
The content is not centred, width of <x-item> is does not grow, probably because <slot> does not inherit property settings and as the result DOM <x-item> width equals to content width.
Did this work before? N/A
Does this work in other browsers? N/A
Chrome version: 54.0.2840.71 Channel: n/a
OS Version: OS X 10.11.6
Flash Version: Shockwave Flash 24.0 r0
Meanwhile, if to do the same without shadowDOM everything works as expected. This is because there is not intermediate <slot> interaction. (see attached screens).
,
Jan 23 2017
,
Jan 24 2017
Thank you for the feedback. You might want to see the current limitation of slots in Blink. https://bugs.chromium.org/p/chromium/issues/detail?id=660265 However, at the first glance, regardless of bug 660265 , it looks your example should work. I appreciate if you can show code via jsfiddle or jsbin.
,
Jan 24 2017
,
Jan 24 2017
Guessing this is not platform specific.
,
Jan 24 2017
Hi, Yes, I've read about 660265 before I posted this bug, and had same opinion that in my case everything should work...However, in reality it doesn't work. :) Here is an example -> https://jsfiddle.net/re1evafn/ You would see that in #shadowDOM the x-element has display property of 'block' which means to my understanding that <slot> did not pass property to an slot='x-element'. So, as a conclusion it is pure inheritance bug. Please, correct me if I am wrong or I do it in a wrong way.
,
Jan 24 2017
In your jsfiddle demo, I put some text in <x-element>'s <div class='xElement'>, the text didn't get centered, even though from the inspector I see 'justify-content: center' is applied. On the other hand, if I put 'color: red' in .xElement class style rules in x-element template, the text turned red and looks inherited to the slotted "some random content". I'm not familiar with flexbox layout, but could be an issue of flex box layout (in combination with shadow DOM). Maybe this is an expected behavior. +cbiesinger if he has any insight for what is happening in the jsfiddle demo.
,
Jan 24 2017
See https://jsfiddle.net/re1evafn/1/ for what I modified in #7. (added "color: red;" in .xElement, added "aaaaa" in <div class='xElement'>)
,
Jan 24 2017
Your xElement is not display:flex, it's display:block. I don't really know how shadow dom works but this is not a flexbox problem...
,
Jan 24 2017
This does get fixed by adding:
this.setAttribute('class', element.getAttribute('class'));
after this.setAttribute('slot', this._name);
,
Jan 24 2017
,
Jan 24 2017
Hm... I think there is some miss understanding.
I will try to make it clearer.
As you know in CSS there are many properties, some of them are inherited by default and others not.
For example:
p { color: green }
<p>This paragraph has <em>emphasized text</em> in it.</p>
the words "emphasized text" will appear green, since the <em> element has inherited the value of the color property from the p element. This inheritance come automatically "by default".
However, there are cases when property does not inherit by default.
For example:
p { border: medium solid }
<p>This paragraph has <em>emphasized text</em> in it.</p>
the words "emphasized text" will not have a border (since the initial value of border-style is none) and it is not specified explicitly on child element <em> that we want to inherit this 'border' property.
More detailed info here:
https://developer.mozilla.org/en-US/docs/Web/CSS/inheritance
So, in this example -> https://jsfiddle.net/re1evafn/
There are 2 case.
First case is pure lightDOM.
Second, using shadowDOM.
In the first case, the inheritance of 'flex' property goes like this:
div.xItem -> div.inner -> .xElement -> div.inner -> div (which is centred)
Why it goes like this ?
Because, it was explicitly specified in CSS to inherit 'flex' property from the parent.
And as you can see it works on the first rectangular.
However, in second case the inheritance of 'flex' property goes differently for custom elements:
.xItem -> .inner -> slot -> .xElement -> .inner -> div
So the difference is that in the first scenario there is not <slot> element and therefore the inheritance goes straight form div.xItem -> div.inner to -> .xElement.
In the second scenario, it goes from .xItem -> .inner -> slot -> and slot has 'display' block and then to -> .xElement.
I was assuming that <slot> would inherit from parent element all properties or at least those that explicitly set on to the .inner selector, and then pass it to child element, which is -> '.xElement'.
To my understanding, <slot> is just like some sort of hole where we could put elements. End its "job" to take everything that was given and pass it further to element that was put in...
,
Jan 24 2017
During explanation of the problem got clearer understanding for myself. So tried to style the <slot> element explicitly to inherit 'display' property. Lines 14-16 at -> https://jsfiddle.net/re1evafn/2/ As the result now it now works and text is centred. Then, the core question is the following -> should the <slot> element receive properties and then pass it submitted element automatically or not...? If yes, then it is a bug, if not then it is bit silly, as required unnecessary extra definitions using ::slotted selector... I will try to find an answer in specs tomorrow...
,
Jan 24 2017
Tried to find <slot> specification regarding inheritance and did not find anything. However, read about 'display' property: -> https://www.w3.org/TR/CSS22/visuren.html#display-prop and it looks like the problem was here. The 'display' property is not inherited from parent element. Therefore, for all properties that are not inherited by the specification, it is necessary to specify inheritance explicitly. Even, if it does not make sense for <slot> element, according to above specification it is not a bug, so believe it issue can be closed.
,
Jan 25 2017
d.veliks@, thanks for your detailed report.
I was kinda short-sighted to answer in comment #7, but to explain what is
happening in the original jsfiddle demo, the trick is that your
<x-item> and <x-element> will have 'display: inline' by default,
for a custom element. So here is dump of all elements involved:
<x-item> (display: inline)
:shadow-root
<div class="xItem"> (display: flex)
<div class="inner"> (display: inherit = flex)
<slot> (*2)
<x-element> (display: block (*1))
:shadow-root
<div>some random element</div> (display: inherit = block)
(*1) this is not inline but block - because it is contained in display: flex.
https://drafts.csswg.org/css-flexbox/#flex-items
https://drafts.csswg.org/css-display-3/#transformations
(*2) for <slot>, it has "display: contents" as default (UA style)
https://drafts.csswg.org/css-scoping-1/#slots-in-shadow-tree
but not yet implemented in Blink.
https://bugs.chromium.org/p/chromium/issues/detail?id=660265
https://bugs.chromium.org/p/chromium/issues/detail?id=657748
Currently, the existence of <slot> is just ignored in the style
inheritance, thus <x-element> inherits properties from
<div class="inner">.
So to realize what you intended originally, you have to specify
"display: inherit" on <x-element> itself.
So either
1. add "x-element { display: inherit; } in main CSS
2. add "::slotted(x-element) { display: inherit; }" in x-item's
stylesheet
3. add ":host { display: inherit; }" in x-element's stylesheet
or some variant of above (adding style="display: inherit" on x-element,
or add class="xElement" as cbiesinger@ commented on #10 etc. etc.) works.
So in summary, this is working as expected.
,
Jan 25 2017
Hi kochi, Thank you for detailed explanation, very appreciate. |
||||||||
►
Sign in to add a comment |
||||||||
Comment 1 by d.vel...@gmail.com
, Jan 20 2017For those who faced the same issue, here is the temporary solution until the bug is fixed. It fixes shadowDOM, but affects normal DOM. But this should not be a problem as it is expected that shadowDOM CSS is independent of DOM CSS. Steps to solve: 1. add properties to host :host{ display: inherit; flex-flow: column wrap; flex: inherit; align-items: center; } 2. Adjust .element properties .element{ display: inherit; flex-flow: row wrap; flex: inherit; align-items: center; }119 KB
119 KB View Download
144 KB
144 KB View Download