Polymer / polymer

Our original Web Component library.
https://polymer-library.polymer-project.org/
BSD 3-Clause "New" or "Revised" License
22.04k stars 2.01k forks source link

Polymer 1 Slotting does not play nice in Firefox & Safari #5539

Closed katlyn-edwards closed 5 years ago

katlyn-edwards commented 5 years ago

Description

Slot is greedy and taking non-slotted elements in Firefox

Live Demo

https://codepen.io/anon/pen/joWRpr?editors=1010

expectation: each page has different text saying that it's being shown. this happens in chrome reality: firefox shows all content on the first page, and it's a mess

Browsers Affected

Don't have access to Edge, sorry.

Versions

bicknellr commented 5 years ago

This should be fixed as of v1.12.0.

bicknellr commented 5 years ago

Sorry, here's an actual explanation:

Polymer 1 uses the deprecated Shadow DOM v0 spec under the hood and tries to use the native implementation of it, if available. Polymer 1 also has a built-in polyfill that maps the Shadow DOM v1 spec back onto the v0 spec ('hybrid') by replacing <slot>s in your template with <content>s and copying all attributes from one to the other. When copying, it also converts the name attribute of your <slot> to a roughly equivalent select attribute on the <content>: name="x"select="[slot=x]". It's important to note that a binding without the $ suffix, like select="[[value]]", does not cause polymer to update the select attribute when value changes: it only sets the select property of the element. Also, Chrome still has a deprecated, native implementation of Shadow DOM v0 and, in this native implementation, setting the select property of a <content> element does affect the distribution through that <content>. So, Polymer 1 converted your name="[[value]]" binding to a select="[slot=[[value]]]" on the content, which works in Chrome because Chrome's deprecated Shadow DOM v0 implementation responds as expected to the select property being set. However, the Shadow DOM v0 polyfill in Polymer 1 does not redistribute nodes on changes to the select property of <content>s - it only redistributes when the select attribute changes - so name="[[value]]" that was converted to select="[slot=[[value]]]" doesn't update the distribution. Also, Polymer 1 didn't convert name$= attribute bindings to select$= so the workaround would have been to add a content attribute to your slot, which doesn't make any sense.

tl;dr: Chrome's native Shadow DOM v0 made it look like this should work, but it didn't. #5540 adds support for changing distribution in response to bindings to the name attribute on slots, even if Polymer 1 ends up using the deprecated Shadow DOM v0 spec. This should be fixed if you update to v1.12.0 and change name="[[value]]" to name$="[[value]]".