Sharing styles between shadow DOM
Developers love to complain about the “global scope” of CSS. Shadow DOM offered a solution, but has been met with its own complaints. The style encapsulation offered by shadow DOM is great, but it also has drawbacks. Did I need to define * { box-sizing: border-box; }
for every different component? Could I not use any CSS utility classes? These were some of the immediate questions I had when first working with shadow DOM, and the answers didn’t please me.
CSS module scripts offer a solution. We can opt-in to certain shared styles, while still avoiding the global scope of CSS.
import sharedStyles from "./shared.css" with { type: "css" };
import cardStyles from "./card.css" with { type: "css" };
class MyCard extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
this.shadowRoot.adoptedStyleSheets.push(sharedStyles, cardStyles);
}
connectedCallback() {
this.shadowRoot.innerHTML = "<div><slot></slot></div>";
}
}
customElements.define("my-card", MyCard);
Opting in to the shared stylesheet is only one line of code per component.
To share styles between both light DOM and shadow DOM, request the shame stylesheet in a link tag:
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="shared.css"> <!-- shared.css gets applied to light DOM -->
</head>
Read more about import attributes and CSS modules here.