5
votes

https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom

This got me all excited I could write my own custom webpage from scratch without polymer.

Only to find out css :host for example is not working in Edge and FireFox. I can deal without html import for now until w3c figured out what they want to do with es6 modules, but each browser having their own half implemented Shadow DOM version without css is pushing my buttons.

So I still need a full polymer stack to have webcomponents in all browsers.

<script src="../webcomponentsjs/webcomponents-lite.js"></script>

<link rel="import" href="../hello-world.html">

<hello-world>Hello World Polymer 2.x</hello-world>

Does anybody know how to polyfill Edge and FireFox to have a actually Shadow DOM, not a native Shadow DOM that's pretending to be one?

This is what I tried, but I can't figure out how to tell Edge and FireFox to put their Shadow wannabe somewhere else and use the shadydom/shadycss.

https://jsbin.com/quvozo

<!DOCTYPE html>
<html>

<head>
  <title>Components</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0"/>
</head>

<body>
  <hello-world>Hello World ES2015</hello-world>
  <script>
    function loadScript(src, main) {
      return new Promise(function(resolve, reject) {
        const script = document.createElement('script');
        script.async = true;
        script.src = src;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
      });
    }
    let polyfilled = false;
    const loadPromises = [];
    if (!('customElements' in window)) {
      loadPromises.push(loadScript('https://raw.githubusercontent.com/webcomponents/custom-elements/master/custom-elements.min.js'));
    }
    if (!HTMLElement.prototype.attachShadow) {
      polyfilled = true
      loadPromises.push(loadScript('https://raw.githubusercontent.com/webcomponents/shadydom/master/shadydom.min.js'));
      loadPromises.push(loadScript('https://raw.githubusercontent.com/webcomponents/shadycss/master/shadycss.min.js'));
    }
    Promise.all(loadPromises)
      .then(e => console.log(`polyfilled ${polyfilled}`))
      .then(e => {
        class HelloWorld extends HTMLElement {
          constructor() {
            super()
            this.template = document.createElement('template')
            this.template.innerHTML = `
              <style>
                :host {
                  display: block;
                  box-sizing: border-box;
                  border: 1px solid red;
                  margin-top: 10px;
                  padding: 0px 5px;
                }
              </style>
              <p>Test <slot></slot></p>
            `
            if (polyfilled) ShadyCSS.prepareTemplate(this.template, 'hello-world');
          }
          connectedCallback() {
            const shadowRoot = this.attachShadow({ mode: 'open' })
            shadowRoot.appendChild(this.template.content.cloneNode(true))
            if (polyfilled) ShadyCSS.applyStyle(this);
          }
        }
        customElements.define('hello-world', HelloWorld)
      })
  </script>
</body>

</html>
1
This was an entertaining read, thanks. In fairness, the standards (yes, plural) are still far from mature and Microsoft Edge is still relatively new. Microsoft has already announced that they'll be taking steps to implement web components but it will take a while. It doesn't help that Shadow DOM itself went through a complete rewrite in the first place. It's not easy for the browser vendors.BoltClock♦
I understand and part of me is glad they are doing their best, but my frustration aside I was hoping somebody could help me how to use the polyfill shadycss corectly from github.com/webcomponents I know its possible because polymer is doing it. I just want to know how exactly because the article doesn't take a partly native shadow dom into account. ThanksGert Cuykens

1 Answers

3
votes
  • Shadow DOM polyfill won't create a real Shadow DOM but normal DOM elements,
  • The Custom Elements specification won't allow you to add elements in the normal DOM tree in constructor(),

Therefore, you should attach the fake Shadow DOM afterwards, that is inside the connectedCallback() method, instead of inside the constructor() method.

The ShadyCSS polyfill works fine with Edge and Firefox.