Plotly.js is incompatible with Chrome's native shadow DOM implementation
See original GitHub issueContext
I develop and maintain ginkgobioworks/plotly-plot, a Polymer element that encapsulates plotly.js. Polymer is a web-component framework written by Google, which uses browser functionality known as the “shadow DOM” to isolate the internals of web components from the rest of the page.
Polymer 1.x has two kinds of shadow DOM implementations: native shadow DOM (v0), and a shim called “shady DOM.” Native shadow DOM is newer and yields improved performance, but it has poor support in browsers outside of Chrome and can cause problems with existing code. For this reason, shady DOM is still the default implementation in Polymer 1.x.
Issue
Unfortunately, native shadow DOM is currently incompatible with plotly.js. The icon toolbar layout code in the plotly.js library fails for all plotly plots rendered inside a shadow DOM.
Example
Since it’s a pain to create your own elements without the tools in a code pen, the easiest example to observe is on the plotly-plot demo page.
You can render the page either with shady DOM (the default) or with shadow DOM by passing in the ?dom=shadow
GET parameter, which forces Polymer to use native shadow DOM v0 in browsers that support it.
Expected/Observed
Under shady DOM (no GET parameter), the elements behave as expected. Under shadow DOM (with the GET parameter), however, the toolbars fail to render entirely.
Impact
I don’t know why this is the case. It might have to do with SVG support for the buttons, or CSS effects.
The work-around on my side is that anyone who consumes my element must not turn on native shadow DOM rendering on any page that renders a plotly-plot
widget. This is fine for small, simple pages, but can be a real drag when front-end performance is at stake.
I’m wondering if there might be a relatively easy fix that would prevent this from happening—if there is, it’d be nice to do it. If not, it’s probably not worth doing any serious rewriting for this use case.
In any case, thought you’d be interested to know.
Issue Analytics
- State:
- Created 7 years ago
- Comments:11 (2 by maintainers)
Top GitHub Comments
I believe the problem is in the way that plotly adds style to the document. When the plotly.js script is loaded it initializes itself by running the following function for a number of css styles:
This appends a new style tag to the head of the document. Chrome doesn’t seem to totally understand this because if you try to inspect the element it just appears empty. This is not a problem if you are not using a shadowRoot as the styles are still correctly applied. However, in a shadowRoot the style encapsulation screws things up and the styles are not found.
You can get around this by adding the required styles to your template style section. This is kind of a mess but it does work. I have created an example project that shows the initial problem and the hack working at: plotly-polymer-fix
There is a script at happybase that claims to be a cross-browser way to create css styles dynamically. I replaced the original implementation of addStyleRule with this one and it also does not work.
This is because css must be defined inside the component’s shadow dom. Just generate the final css and do what you need with it:
sass .\node_modules\plotly.js\src\css\style.scss > plolty.css
Then do what you want with css, if you are using lit-element your can expose the css this way:
Then you are free to import this piece of css in your individual components.