1

I'm trying to work with just ShadowDOM v1 (no Polymer or other web components) but I can't get the styling to work with a polyfill.

The special :host and ::slotted CSS selectors are not working.

I've tried with various polyfills, but TBH, I'm a bit lost. I have seen this question, but it's using custom elements and templates. My scenario is without these.

Can anyone help me make this code work in Firefox or Edge? - specifically, you should see three colors: blue, red and yellow, but only red works.

const shadowHtml =
  `<style>
    :host {
      background: yellow;
    }
    .inside {
      background: red;
      margin: 10px;
    }
    ::slotted(div[slot="content"]) {
      background: blue;
      color: white;
    }
    </style>
    <div>
      <p>i am yellow</p>
      <div class=inside>i am red</div>
      <slot name="content"></slot>
    </div>`;
  

const root = document.querySelector('#root');
const shadow = root.attachShadow({ mode: 'open' });
shadow.innerHTML = shadowHtml;
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Shadow DOM v1 Test</title>
  <script src="https://rawgit.com/webcomponents/webcomponentsjs/v1/webcomponents-lite.js"></script>
</head>
<body>
  <div id=root>
    <div slot="content">
      <p>I am blue</p>
    </div>
  </div>
</body>
</html>
Supersharp
  • 29,002
  • 9
  • 92
  • 134
Phil Mander
  • 1,819
  • 15
  • 20

1 Answers1

3

webcomponents-lite.js "v1" now embeds a Shadow DOM v1 polyfill:

  • the ShadyDOM shim which provides attachShadow()
  • the ShadyCSS object which simulates :host and ::slotted().

Note that to use it you'll have to put your template string inside a <template> element in order to call ShadyCSS.prepareTemplate()

const makeTemplate = function (strings) {
    const template = document.createElement('template');
    template.innerHTML = strings[0];
    return template;
}

const shadowHtml =
  makeTemplate`<style>
    :host {
      background: yellow;
    }
    .inside {
      background: red;
      margin: 10px;
    }
     ::slotted(div[slot="content"]) {
      background: blue;
      color: white;
    }
    </style>
    <div>
      <p>i am yellow</p>
      <div class=inside>i am red</div>
      <slot name="content"></slot>
    </div>`
ShadyCSS.prepareTemplate(shadowHtml, 'div');
  
const root = document.querySelector('#root');
const shadow = root.attachShadow({ mode: 'open' });
shadow.innerHTML = shadowHtml.innerHTML;
<script src="https://cdn.rawgit.com/webcomponents/shadydom/master/shadydom.min.js"></script>
<script src="https://cdn.rawgit.com/webcomponents/shadycss/master/scoping-shim.min.js"></script>

<div id=root>
  <div slot="content">
    <p>I am blue</p>
  </div>
</div>
Supersharp
  • 29,002
  • 9
  • 92
  • 134
  • Thanks so much for this! Btw, The code snippet I included was using the polyfill from the [v1 branch](https://github.com/webcomponents/webcomponentsjs/tree/v1) which does actually include Shadow DOM support in **webcomponents-lite.js**. It also seems to have **ShadyCSS** included too and the your solution continues to work using this instead. I'm assuming the ShadyDOM and ShadyCSS polyfills are currently more stable though. – Phil Mander Feb 19 '17 at 09:32
  • 1
    @PhilMander you're right! I've corrected my answer. – Supersharp Feb 19 '17 at 10:10
  • I'm making a library of custom elements, thus writing in JS, so it seems impractical to have to use JavaScript to create a template element and put it into DOM just so that I can get it's content for my custom element using ShadyDOM. I'd like to just use template strings, and I want for it to work with native shadow Dom, bit just shady Dom, so this answer doesn't answer for my case unfortunately. (Or did I miss something?) – trusktr Dec 07 '17 at 01:36
  • @trusktr template doesn't need to be put into the DOM – Supersharp Dec 07 '17 at 11:02
  • Oops, you're right. I guess I don't want to have to create a template element at all. I just want to do the following, so I asked on their GitHub if it's possible (isn't clear if it is): https://github.com/webcomponents/shadycss/issues/144 – trusktr Dec 11 '17 at 20:40