In the scenario where you are developing a component that does not utilize ShadowDOM, it may still be necessary to incorporate your CSS into a shadowRoot. This is crucial for instances where another individual embeds your component within their shadowDOM, requiring you to add your CSS to their shadowRoot. Achieve this by implementing the following code snippet:
const myStyle = document.createElement('style');
myStyle.setAttribute('component', 'my-el');
myStyle.textContent = ` button {
padding: 8px 20px;
}
.happy-btn {
background-color: pink;
}
.sad-btn {
background-color: #007;
color: white;
}`;
function addCss(el, selector, styleEl) {
// Verify if the component is placed in a shadow root.
// If so, insert CSS into that shadow root.
let doc;
try {
doc = el.getRootNode();
if (doc === document) {
doc = document.head;
}
}
catch(_ex) { doc = document.head; }
if (!doc.querySelector(selector)) {
doc.appendChild(styleEl.cloneNode(true));
}
}
class MyEl extends HTMLElement {
constructor() {
super();
addCss(this, 'style[component="my-el"]', myStyle);
}
connectedCallback() {
this.innerHTML = `<div class="spaced"><button class="happy-btn">I'm Happy</button></div>
<div class="spaced"><button class="sad-btn">I'm Sad</button></div>`;
}
}
customElements.define('my-el', MyEl);
class TheirEl extends HTMLElement {
constructor() {
super();
this.attachShadow({mode:'open'});
this.shadowRoot.innerHTML = `<hr/><my-el></my-el><hr/><my-el></my-el><hr/>`;
}
}
customElements.define('their-el', TheirEl);
<their-el></their-el>
The addCss
function will correctly position your CSS within the appropriate shadowRoot or document.head
if no shadowRoot exists.
It is essential to call addCss
within your constructor to ensure that the CSS is placed in the correct location and prevent duplicate additions as long as a unique selector is used to identify your <style>
element.
In the provided example, the <style>
tag includes an attribute named component
with the value of the component name (component="my-el"
). Utilize the selector 'style[component="my-el"]' to determine if the tag already exists in the shadowRoot or document.head
, adding the styles only if it is absent.
It is unwise to assume that your component will never be placed in shadow DOM just because it is currently not using it. Implement the above approach to safeguard your component.
Additional Note
If you opt for shadow DOM usage, this issue is eliminated since you must include your CSS in your own shadowRoot.