You have to apply the style to the shadow DOM. A common but soon-to-be-outdated technique is to add a <style>
element to the shadow DOM and set its text contents as the CSS you want to apply within the custom element.
The snippet below does just that. The style is saved to a variable, but you can place it anywhere as long you're conscious of how often its context is run. Following Intervalia's advice, it's best to apply a style to the custom element using :host
.
It's also possible to add a <link>
element instead, but that may cause the element to pop-in without a style (FOUC)
const myElementStyle = `
:host {
border: 1px solid black;
}
span {
font-weight: bold;
}
`
class MyElement extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({mode: 'open'});
const style = document.createElement('style');
style.textContent = myElementStyle;
shadow.appendChild(style);
shadow.appendChild(document.createTextNode('Yadda blah'));
const span = document.createElement('span');
span.appendChild(document.createTextNode('Can I style U?'));
shadow.appendChild(span);
}
}
customElements.define('my-element', MyElement)
<my-element></my-element>
Another option is to use Constructable Stylesheets, which should soon be available in modern browsers. These let you create a stylesheet object that can embed styles or import styles from external resources.
I wrote up an answer here, so I'll just post a snippet that answers your question:
const customSheet = new CSSStyleSheet();
customSheet.replaceSync(`
:host {
border: 1px solid black;
}
span {
font-weight: bold;
}
`);
class MyElement extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({
mode: 'open'
})
shadow.adoptedStyleSheets = [customSheet];
shadow.appendChild(document.createTextNode('Yadda blah'))
const span = document.createElement('span')
span.appendChild(document.createTextNode('Can I style U?'))
shadow.appendChild(span)
}
}
customElements.define('my-element', MyElement)
<my-element></my-element>