Почему мой веб-компонент CSS не отображается? Я не использую shadowDOM
У меня есть компонент Native V1, который не использует shadowDOM, поэтому я помещаю свой CSS в <head>
, Но когда кто-то еще использует мой компонент, мой CSS больше не работает.
Это происходит только в том случае, если их компонент использует shadowDOM.
Пример кода для моего компонента:
class MyEl extends HTMLElement {
constructor() {
super();
}
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>`;
}
}
// Define our web component
customElements.define('my-el', MyEl);
button {
padding: 8px 20px;
}
.happy-btn {
background-color: pink;
}
.sad-btn {
background-color: #007;
color: white;
}
<my-el></my-el>
Мой CSS загружен в <head>
тег, так как я не использую shadowDOM. Но как только внешний элемент включает меня в их shadowDOM, все рушится.
1 ответ
Если вы создаете компонент, который НЕ использует ShadowDOM, вам все равно может понадобиться добавить свой CSS в shadowRoot. Если кто-то еще поместит ваш компонент в свое shadowDOM, вы должны добавить свой CSS в их shadowRoot. Вы можете сделать это с помощью следующего кода:
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) {
// Check to see if we have been placed into a shadow root.
// If we have then add our CSS into that shadow root.
let doc;
try {
doc = el.getRootNode();
if (doc === document) {
doc = document.head;
}
}
catch(_ex) { doc = document.head; } // Shadow DOM isn't supported.
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>
Функция addCss
поместит ваш CSS в правильный shadowRoot или в document.head
если нет shadowRoot.
Вы должны позвонить addCss
в вашем конструкторе, чтобы разместить CSS в правильном месте. Эта процедура также гарантирует, что вы не добавите ее дважды, если у вас есть уникальный селектор для идентификации вашего <style>
тег.
В моем вы видите <style>
тег добавляет атрибут с именем component
со значением имени компонента. В моем случае component="my-el"
,
Затем я использую селектор 'style [component = "my-el"] ", чтобы посмотреть, есть ли этот тег уже в shadowRoot, или document.head
если не существует shadowRoot, и добавляйте стили только в том случае, если он еще не существует.
Вы не можете предполагать, что ваш компонент не будет находиться в теневой DOM только потому, что вы его не используете. Используйте пример выше, чтобы защитить себя.
Примечание
Если вы используете shadow DOM, то эта проблема исчезнет, так как вам придется поместить свой CSS в ваш собственный shadowRoot.