Многие из этих библиотек oldskool используют document.
для доступа к основному DOM.
Таким образом, они ничего не могут сделать с контентом в shadowDOM
Это означает, что ваша цель - не кровоточить сценарии выход невозможен.
Font-Awesome (сценарий и стили) должны быть загружены в основной DOM.
Если вы не хотите удалять стили за пределами shadowDOM, вы должны играть с помощью правила:
Значения Font-Awesome должны оставаться в главном DOM
lightDOM является (основным DOM) 'original' для shadowDOM содержимого со слотами
lightDOM оформляется основным DOM
(или его контейнером shadowDOM, если сам элемент находится внутри другого shadowDOM )
с прорезями lightDOM остается в lightDOM , только отражается до <slot></slot>
Вы не хотите повторять определения значков FontAwesome в каждом lightDOM
(вы также можете не тогда используйте пользовательских элементов)
<span class="fa-4x fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
- Пользовательский элемент может получить доступ ко всему DOM
Решение:
Напишите пользовательский элемент, который
- создает свой собственный lightDOM
- , который имеет слот
<slot></slot>
( отражено! не перемещен! ) - принимает конфигурацию из атрибутов
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<awesome-icon></awesome-icon>
JSFidlle: https://jsfiddle.net/CustomElementsExamples/1pmvasnj/
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer></script>
<script>
customElements.define('awesome-icon', class extends HTMLElement {
constructor() {
super().attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
}
connectedCallback() {
let setProperty =
(prop, value)=>this.shadowRoot.host.style.setProperty('--' + prop, value);
setProperty('fa-background', this.getAttribute('background'));
setProperty('fa-color', this.getAttribute('color'));
// move icon HTML back to lightDOM so FontAwesome can style it
this.innerHTML = this.shadowRoot.querySelector('#ICON').innerHTML;
}
});
</script>
<template id="AWESOME-ICON">
<style>
::slotted(*) {
/* lightDOM SPAN has higher Specificity, only way out is using !important */
background: var(--fa-background,grey) !important;
color: var(--fa-color,darkgrey) !important;
}
</style>
<template id="ICON">
<span class="fa-4x fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
</template>
<slot><!--lightDOM REFLECTED here--></slot>
</template>
<awesome-icon><!-- lightDOM CREATED here --></awesome-icon>
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<style>
span{
background:lightblue; /* !important inside shadowDOM overrules these settings */
color:red;
}
</style>
НЕ с использованием shadowDOM и SLOT-ов
И, опираясь на свойства scoped CSS, код упрощается:
<script>
customElements.define('awesome-icon', class extends HTMLElement {
connectedCallback() {
this.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.style.setProperty('--fa-background', this.getAttribute('background') );
this.style.setProperty('--fa-color' , this.getAttribute('color') );
}
});
</script>
<template id="AWESOME-ICON">
<span class="fa-4x fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
</template>
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<awesome-icon></awesome-icon>
<style>
span {
background: var(--fa-background);
color: var(--fa-color );
}
</style>