Search code examples
javascriptcomponentsslotsnative-web-component

Slots does not work on a html web component without shadow dom


I have a html web component without shadow dom and I try to add a slot. For some reason it does not work.

I expected it to switch "Foo bar" to "Hello world" but that does not happen.

  1. Does slots only works with shadow dom and a template?
  2. How can I get it to work?

class HelloWorld extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.innerHTML = `
      <div>
        <slot name="element-name">Foo Bar</slot>
      </div>
    `;
  }
}

customElements.define("hello-world", HelloWorld);
<hello-world>
  <span slot="element-name">Hello World</span>
</hello-world>


Solution

  • Yes, <slot> only works inside shadowDOM in a native (JSWC) Web Component

    or native HTML Element (you can attach shadowDOM to)

    Slotted content is reflected lightDOM content

    See: ::slotted CSS selector for nested children in shadowDOM slot

    A Web Component without shadowDOM only has innerHTML

    If you do this.innerHTML= on such a Web Component it replaces the innerHTML, just like on any other HTML tag

    with shadowDOM:

    <hello-world>
      <b slot="none">Mighty</b>
      <span slot="title">Web Components</span>
      Hello! 
    </hello-world>
    
    <script>
    customElements.define("hello-world", class extends HTMLElement {
      constructor() {
        super()
          .attachShadow({mode:"open"})
          .innerHTML = `<slot></slot><slot name="title">Foo Bar</slot>`;
        this.onclick = (evt) => this.querySelector('b').slot = "title";
      }
    });
    </script>