During development, there will still be situations where external CSS needs to be imported into Shadow DOM, so how to deal with it? The author gives the following schemes for the situation encountered recently.
One, @import
Sample code
const template = document.createElement('template');
class WhatsUp extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innderHTML = `
<style>
@import "./index.css"; // 核心代码
</style>
<div>Sup</div>
`
}
}
window.customElements.define('whats-up', WhatsUp);
Advantages: This method is very compatible, click to view caniuse .
Disadvantage: performance
Two,::part
::part
CSS pseudo-element represents any element in the shadow tree that matches the attribute of part
Sample code
HTML
<template id="whats-up">
<div part="sup">Sup</div>
<div part="foo">Sup</div>
</template>
<whats-up></whats-up>
CSS
whats-up::part(sup) {
/* 样式作用于 `sup` 部分 */
}
whats-up::part(foo) {
/* 样式作用于 `foo` 部分 */
}
Advantages: concise and clear
Disadvantages: Compatibility is not very good, click to view caniuse .
Three, var
CSS custom properties can penetrate into Shadow DOM!
Sample code
JS
const template = document.createElement('template');
template.innerHTML = `
<style>
button {
background: var(--background);
color: var(--color);
padding: var(--padding);
font-size: var(--font-size);
border: 0;
}
</style>
<div>Sup</div>`;
CSS
whats-up {
--background: #1E88E5;
--color: white;
--padding: 2rem 4rem;
--font-size: 1.5rem;
}
Advantages: good compatibility
Disadvantages: relatively limited, only a few can be set externally, and the style cannot be "flying freely"
Fourth, pass in through attributes
Sample code
JS
class Whatsup extends HTMLElement {
static get observedAttributes() {return ['css']}
constructor() {
super();
}
get css() {
return this.getAttribute('css');
}
set css(value) {
if (value === null || value === false) {
this.removeAttribute('css');
} else {
this.setAttribute('css', value);
}
}
connectedCallback() {
const shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.innerHTML = `
<style>
:host{
display: flex;
}
${this.css} // 核心代码
</style>
<div class="name">Sup</div>
`;
}
}
HTML
<whats-up
css="
.name{
color: red;
}
"
></whats-up>
Advantages: The style can be modified at will
Disadvantages: the code is not elegant enough
Five, custom component internal definition modification style function
Sample code
JS
class Whatsup extends HTMLElement {
// ...
// 核心代码
reStyle(els, styles) {
const elements = Array.isArray(els) ? els : [els];
elements.forEach((element) => Object.assign(element.style, styles));
}
}
HTML
<whats-up></whats-up>
<script>
const myEle = document.querySelector('whats-up')
const title = myEle.shadowRoot.querySelector('.title');
myEle.reStyle(title, {
color: 'red',
width: '200px',
})
</script>
Six, set the style through the slot outside
Sample code
JS
class WhatsUp extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<div>
<slot name="header"></slot>
</div>
`;
}
}
customElements.define('whats-up', WhatsUp);
HTML
<style>
.header{
color: red;
}
</style>
<whats-up>
<div slot="header" class="header">
what's up
</div>
</whats-up>
Seven, fetch acquisition
Sample code
class WhatsUp extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
// 获取样式
fetch('./index.css').then(res => res.text()).then(data => {
let node = document.createElement('style');
node.innerHTML = data;
this.shadowRoot.appendChild(node);
});
// ...
}
}
customElements.define('whats-up', WhatsUp);
Advantages: The advantage is that the compatibility is good, the elements that support Shadow DOM all support this syntax; and the performance is OK
Disadvantages: not elegant
Eight, CSS module import
This method uses the browser's native import syntax, but CSS files are imported instead of JS files.
That is, the CSS file is directly imported as a module.
Sample code
import styles from "index.css";
class WhatsUp extends HTMLElement {
constructor() {
// ...
// 核心代码
shadow.adoptedStyleSheets = [styles];
}
}
Advantages: The advantage is that it is convenient and fast to use and is the official recommended method, or the import CSS module is only supported for this scenario; and the performance is OK, the import itself is an asynchronous process.
Disadvantages: Poor compatibility, poke here caniuse .
Summarize
Various methods are applicable to different scenarios, so be careful to consume.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。