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.
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>
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>default</slot>` + // default - slotting anything NOT slotted
`<slot name="title">Foo Bar</slot>`;
this.onclick = (evt) => this.querySelector('b').slot = "title";
}
});
</script>
You are dealing with HTML!
Whitespace and linebreaks in HTML are slotted to the default slot!
not existing slotnames are ignored,
content does not go to the default <slot>
!!
The slotname can be changed with JS, see above.
<!-- comments -->
are ignored
The default content of any <slot>
is not slotted content!
<hello-world><span slot="title">Web Components rule!</span></hello-world>
<hr>
<hello-world><!-- comment --><span slot="notAslotname">Frameworks are cool!</span></hello-world>
<hr>
<hello-world>
<span slot="title">Web Components are cool!</span>
</hello-world>
<script>
customElements.define("hello-world", class extends HTMLElement {
constructor() {
super()
.attachShadow({mode:"open"})
.innerHTML = `<${this.localName}> ` +
`<style>::slotted(*){background:lightgreen}</style>` +
`<slot>No whitespace or linebreaks! </slot> ` + // default - slotting anything NOT slotted
`<slot name="title">Web Components take <b>some</b> time to learn</slot>`;
}
});
</script>