How do you scope Polymer @imports/stylesheets which are dynamically injected into an element?

StackOverflow https://stackoverflow.com//questions/22076302

  •  23-12-2019
  •  | 
  •  

Question

I'm currently working on a Polymer element for Prism.js (a syntax highlighter). The element is hosted here and is also in a GitHub repo. What I'm trying to do is allow a user to set an attribute theme which decides which theme file we pull in. A user should be able to set a different theme per element with those styles being correctly scoped.

For example, if you configure the element with <prism-js theme="tomorrow">, when the element initializes we read in the theme value and pull in prism-tomorrow.css by injecting it via an @import. If I have another instance <prism-js theme="coy">, the themes pulled in for each element shouldn't clash.

Unfortunately, although the output for this is correct in Canary (the styles for each element don't clash)..

enter image description here

The styles aren't scoped and clobber each other in Chrome stable:

enter image description here

I'm wondering if there's a reliable way to approach this problem.

To date I have attempted to:

  • Inject my styles with the scoped attribute - this either isn't supported or didn't work
  • Inject a link to the stylesheet which is appended to my shadowRoot - this had the same problem of styles clashing
  • Use shimStyling - same issue
  • Work against my template's stylesheet as per the Polymer docs:

var sheet = document.querySelector('style').sheet; var hostRules = sheet.cssRules[0]; hostRules.cssText = '@import url("' + this.themepath + '");</style>';

Alternatively, I'm wondering if it is possible set up my element so that I can update {{theme}} in my template's @import as follows:

<style> :host { display: block; }; @import 'bower_components/prismjs/prism-{{theme}}.css'; </style>

Though, I'm unsure if getting that to work would solve my scoping issues either. Unfortunately inlining all of the themes is not an option. Any ideas? :)

Was it helpful?

Solution

Sadly, it may not be practical to achieve per-instance theme selection under the ShadowDOM polyfill as it is today.

The CSS scoping available to native ShadowRoot is quite difficult to polyfill. Today the polyfill does lots of tricks and translations in order to provide some scoping while still remaining efficient.

However, there are two categories of scoping issues that are problematic:

  1. per-instance scoping (today the CSS shim operates per-type)
  2. lower-bound encapsulation (an element's styles can leak into other elements in it's subtree)

There are still a lot of things that work well given these constraints, but, in particular, consuming CSS like you want to do is not well supported.

Work is under way to explore imperative support for (simulated) per-instance scoping via the CSS shim. I will endeavor to update this issue if something lands.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top