Shadow DOM CSS Isolation Polyfill

300 views
Skip to first unread message

numtel

unread,
Nov 8, 2014, 2:21:51 AM11/8/14
to polym...@googlegroups.com
Hello,

I've been experimenting with creating a polyfill to isolate styles from shadow DOM elements. It has been fairly straight-forward creating a script that isolates CSS rules from the children of arbitrary DOM elements in a stand alone package but I've run into some issues with the MutationObserver while trying to integrate with Polymer's webcomponents.js. The 'childList' mutations for shadowRoot children never trigger and attribute mutations to custom element ancestors are not triggered either.

Please take a look at my code:

You can see the webcomponent.js integration in test/mockup/webcomponent.html

View in Firefox <=33 or IE 9/10 to see effects

If you click the 'Attribute Change Test' button first, the MutationObserver picks up the class change and performs the update.
If the 'Insert Test' button is clicked first, the child insertion is never observed. Then click the 'Attribute Change Test' button, no attribute changes are observed.
The 'Ancestor Attribute Change Test' fails completely.

Also, any idea on how to access the original querySelector methods without a shim before loading webcomponents.js would be helpful.

Thanks
Ben

numtel

unread,
Nov 8, 2014, 2:43:42 AM11/8/14
to polym...@googlegroups.com
Please disregard the last sentence about the shim. That was referring to something I was experimenting with that didn't lead to anything.

numtel

unread,
Nov 8, 2014, 10:08:44 PM11/8/14
to polym...@googlegroups.com
I have created the following codepen to display the main issue:

The ancestor attribute change test does not produce any mutation events. For some reason, attribute changes on the body or #desc elements that I have added to the observer go unnoticed. The example works fine in chrome.

numtel

unread,
Nov 10, 2014, 3:05:13 AM11/10/14
to polym...@googlegroups.com
Ok, I've got it working. I'm not happy with the way the code is yet but hopefully that will change soon.

I did end up having to create a helper shim file that loads before webcomponents.js to grab an unmodified version of the prefixed css selector matching method.

Also, the script was trying to update styles on the elements before the selecor matcher was ready so I have had to add a setTimeout delay. On my computer, intervals of 0 or 10ms would not cut it. I've placed a value of 100ms for now but I really need to find a better way to do this.

numtel

unread,
Nov 10, 2014, 11:36:03 PM11/10/14
to polym...@googlegroups.com
Those two hacks are now gone... The source and the UX are much better now.

Is this a good place to post about this script? I'm surprised to not have any reply.

Scott Miles

unread,
Nov 11, 2014, 7:20:12 PM11/11/14
to numtel, polymer-dev
Sorry you haven't had any reply. Your project is very interesting. The only reason you aren't getting feedback right away is because at the moment we are focused on non-CSS problems, and we are all at 100% cpu utilization. =P 

If we were in the middle of working on CSS systems, you probably would have received a reply sooner. For now, please hang in there, we will take a look at your code as soon as we are able.

Scott



On Mon, Nov 10, 2014 at 8:36 PM, numtel <b...@latenightsketches.com> wrote:
Those two hacks are now gone... The source and the UX are much better now.

Is this a good place to post about this script? I'm surprised to not have any reply.

Follow Polymer on Google+: plus.google.com/107187849809354688692
---
You received this message because you are subscribed to the Google Groups "Polymer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to polymer-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/polymer-dev/3b9b280e-2e7e-4681-ac86-8571d9687825%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Steve Orvell

unread,
Nov 12, 2014, 1:07:49 PM11/12/14
to Scott Miles, numtel, polymer-dev
This is an interesting idea. We didn't consider this type of approach for Polymer because we thought the performance not be good enough. Do you have a sense of how your approach impacts performance?

Also, does this script isolate shadowRoots from styles applying to shadowRoots of ancestor elements? (e.g. a rule like x-foo[shadow] p { color: red; } blocked from applying to x-foo -> SR -> x-bar -> SR -> p)

bgre...@gmail.com

unread,
Nov 12, 2014, 1:58:40 PM11/12/14
to polym...@googlegroups.com, sjm...@google.com, b...@latenightsketches.com
Performance is definitely the bottleneck to applying this kind of polyfill. I don't have anything concrete as a benchmark yet but in earlier versions I was manually testing with Bootstrap added to the page (100kb of CSS rules) and there was a small delay. I will be figuring out performance specifics a lot more before I try to convince anybody to actually use this approach. I was looking through the examples on the polymer homepage and thought that since they did work already in IE9/10 (surprised that the calculator worked in IE8!) that they would not be good examples to showcase this script so I'll probably come up with an elaborate page that ensures tons of rules will need to be negated.

My inspiration for development was a project that overlays a dialog (of test results) on top of unknown websites. Others on the team balked at my idea of wrapping the entire thing in an iframe (still what I consider the most prudent approach) and suggested I look into WebComponents. Until I can prove that this approach is usable, it's only wishful thinking. My Windows VM for IE testing will show any bottleneck though as I'm running on an I3 1.4ghz dual core laptop. If performance is usable in this environment, it is probably decent elsewhere.

You have caught me on multiple nested shadow root style applications. At this point, one instance of '[shadow]' in a rule will select for any depth of shadow nesting, kind of like a /deep/ selector.

In the near future, I would like to determine a way to improve this. My intuition tells me to split the selector on '[shadow]' then check to see if each ancestral shadowed element matches the leading part of the selector before/after checking if the child element matches the full selector.

I will continue to post updates as I progress. Thanks for your interest!
Reply all
Reply to author
Forward
0 new messages