ShadowDOM を使う CustomElement にグローバルスタイルを適用する
CustomElement のインスタンス作成時に document.adoptedStyleSheets
からグローバルスタイルを取り出して ShadowDOM の adoptedStyleSheets に追加する
注意点: document.adoptedStyleSheets
の変更を検知できないので インスタンス作成後に変更できない
foo-bar { | |
display: block; | |
margin: 10px; | |
} | |
/* not applied */ | |
.box { | |
color: red; | |
} |
<!DOCTYPE html> | |
<script type="module"> | |
import document_only_sheet from "./document-only-style.css" assert { type: "css" } | |
import global_style from "./global-style.css" assert { type: "css" } | |
import { globalStyle } from "./global-style.js" | |
global_style.global_style = true | |
document.adoptedStyleSheets.push(document_only_sheet, global_style) | |
const selector = (sheets) => { | |
return sheets.filter(x => x.global_style) | |
} | |
customElements.define("foo-bar", class extends globalStyle(HTMLElement, selector) { | |
constructor() { | |
super() | |
this.shadowRoot.innerHTML = ` | |
<div class="box"> | |
text | |
</div> | |
` | |
} | |
}) | |
</script> | |
<foo-bar></foo-bar> |
.box { | |
border: 3px solid green; | |
padding: 10px; | |
} |
export const globalStyle = (Base, selector) => { | |
return class extends Base { | |
constructor() { | |
super() | |
const sheets = selector([...this.ownerDocument.adoptedStyleSheets]) | |
const root = this.attachShadow({ mode: "open" }) | |
root.adoptedStyleSheets.push(...sheets) | |
} | |
} | |
} |