1

I'm trying to use ShadowDomv1 (with https://github.com/webcomponents/webcomponentsjs and https://github.com/webcomponents/shadycss) but it's not working.

The ShadowDom by itself works, but the css is not encapsulated (as we can see with the h2 css rule).

It works as intended on Chrome and Safari (but they both support ShadowDomv1 natively).

Am I missing something or is it impossible ?

Here the jsbin : http://jsbin.com/maqohoxowu/edit?html,output

And the code :

<script type="text/javascript" src="https://rawgithub.com/webcomponents/webcomponentsjs/master/webcomponents-hi-sd-ce.js"></script>
<style type="text/css">
    h2 {
        color: red;
        border-bottom: 1px black dotted;
    }
</style>
<h2>h2 red and dotted</h2>

<my-element>
</my-element>

<template id="myElementTemplate">
    <style scope="my-element">
        h2 {color: blue}
    </style>
    <div>
        <h2>h2 blue and not dotted !</h2> <!-- Should not be dotted because of the encapsulation -->
    </div>
</template>

<script type="text/javascript">
    ShadyCSS.prepareTemplate(myElementTemplate, 'my-element');

    class MyElement extends HTMLElement {
        connectedCallback() {
            ShadyCSS.styleElement(this);

            if (!this.shadowRoot) {
                this.attachShadow({mode: 'open'});
                this.shadowRoot.appendChild(document.importNode(myElementTemplate.content, true));
            }
            ShadyCSS.styleElement(this);
        }
    }

    customElements.define("my-element", MyElement);
</script>
Supersharp
  • 29,002
  • 9
  • 92
  • 134
Mathieu Mahé
  • 2,647
  • 3
  • 35
  • 50

3 Answers3

1

You could use the CustomStyleInterface to apply document level styles only to non Shadow DOM:

const CustomStyleInterface = window.ShadyCSS.CustomStyleInterface;
CustomStyleInterface.addCustomStyle(document.querySelector('style.doc-level'));

class MyElement extends HTMLElement {
  connectedCallback() {
      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(document.importNode(myElementTemplate.content, true));
  }
}

customElements.define("my-element", MyElement);
<script src="https://rawgithub.com/webcomponents/webcomponentsjs/master/webcomponents-hi-sd-ce.js"></script>
<script src="https://rawgit.com/webcomponents/shadycss/master/custom-style-interface.min.js"></script>

<style class="doc-level">
  h2 {
    color: red;
    border-bottom: 1px black dotted;
  }
</style>

<h2>h2 red and dotted</h2>

<my-element></my-element>

<template id="myElementTemplate">
    <style>
        h2 {color: blue}
    </style>
    <div>
        <h2>h2 blue and not dotted !</h2> 
    </div>
</template>
Supersharp
  • 29,002
  • 9
  • 92
  • 134
0

As per Mozillas platform status page, Shadow DOM is still under development. https://platform-status.mozilla.org/#shadow-dom

Stefan Reimers
  • 379
  • 4
  • 9
  • That's why I'm trying to use the polyfills ! – Mathieu Mahé Nov 02 '17 at 19:11
  • Having a deeper look into the ScopingShim of ShadyCSS it looks like only CSS rules present in the element are "encapsulated". The styles of the template are rewritten, effectively adding a class with the name of your custom element so h2 of my-element becomes h2.my-element. Such a rewriting does not take into concern what styles are defined outside of the element - so long story short: the shim makes your styles more specific, but do not enforce encapsulation like a native ShadowDOM. – Stefan Reimers Nov 02 '17 at 19:57
  • That's what I saw in the developer console but I wasn't sure everything work as intended ! Do you know a way of doing it ? – Mathieu Mahé Nov 02 '17 at 20:04
  • You could start fiddling around with all defined styles (see https://stackoverflow.com/questions/2952667/find-all-css-rules-that-apply-to-an-element) and overwrite those for your element. But that might be a cumbersome way to go. Alternatively you could set all styles to their initial value, e.g. h2 {all: initial; color: blue;} in your element. But that will also set the headings font-size and font-weight, which might not be what you want. If there was an easier way, ShadyCSS would have gone it, I guess – Stefan Reimers Nov 02 '17 at 20:28
  • Hmm you're right. I will try something with `all: initial` and then put back the default css for firefox. If it's works and if it's good for my boss, it will be a temporary solution waiting for firefox to finish implementing shadowdom :) Thanks for helping ! – Mathieu Mahé Nov 02 '17 at 21:30
0

The polyfill can not emulate the encapsulation of CSS that is handled natively by true ShadowDOM.

Instead, if you plan to use both then avoid using simple CSS selectors. Instead try using a CSS naming pattern like BEM: http://getbem.com/introduction/

This will allow your CSS to work, most of the time, in either true ShadowDOM and in ShadyDOM.

Intervalia
  • 10,248
  • 2
  • 30
  • 60