|
| 1 | +--- |
| 2 | +chapter: 8 |
| 3 | +subtitle: Bringing CSS into ShadowDOM |
| 4 | +hidden: false |
| 5 | +--- |
| 6 | + |
| 7 | +Components with ShadowDOM typically want to introduce some CSS into their ShadowRoots. This is done with the use of [`adoptedStyleSheets`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/adoptedStyleSheets). Catalyst provides a `@style` decorator to more easily add CSS to your component. |
| 8 | + |
| 9 | +If your CSS lives in a different file, you can import the file with using the `assert { type: 'css' }` import assertion. You might need to configure your bundler tool to allow for this. If you're unfamiliar with this feature, you can [check out the web.dev article on CSS Module Scripts](https://web.dev/css-module-scripts/): |
| 10 | + |
| 11 | +```typescript |
| 12 | +import {controller, style} from '@github/catalyst' |
| 13 | +import DesignSystemCSS from './my-design-system.css' assert { type: 'css' } |
| 14 | + |
| 15 | +@controller |
| 16 | +class UserRow extends HTMLElement { |
| 17 | + @style designSystem = DesignSystemCSS |
| 18 | + |
| 19 | + connectedCallback() { |
| 20 | + this.attachShadow({ mode: 'open' }) |
| 21 | + // adoptedStyleSheets now includes our DesignSystemCSS! |
| 22 | + console.assert(this.shadowRoot.adoptedStyleSheets.includes(this.designSystem)) |
| 23 | + } |
| 24 | +} |
| 25 | +``` |
| 26 | + |
| 27 | +Multiple `@style` tags are allowed, each one will be applied to the `adoptedStyleSheets` meaning you can split your CSS without worry! |
| 28 | + |
| 29 | +```typescript |
| 30 | +import {controller} from '@github/catalyst' |
| 31 | +import UtilityCSS from './my-design-system/utilities.css' assert { type: 'css' } |
| 32 | +import NormalizeCSS from './my-design-system/normalize.css' assert { type: 'css' } |
| 33 | +import UserRowCSS from './my-design-system/components/user-row.css' assert { type: 'css' } |
| 34 | + |
| 35 | +@controller |
| 36 | +class UserRow extends HTMLElement { |
| 37 | + @style utilityCSS = UtilityCSS |
| 38 | + @style normalizeCSS = NormalizeCSS |
| 39 | + @style userRowCSS = UserRowCSS |
| 40 | + |
| 41 | + connectedCallback() { |
| 42 | + this.attachShadow({ mode: 'open' }) |
| 43 | + // adoptedStyleSheets now includes our 3 stylesheets! |
| 44 | + console.assert(this.shadowRoot.adoptedStyleSheets.length === 3) |
| 45 | + } |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +### Defining CSS in JS |
| 50 | + |
| 51 | +The `@style` decorator takes a constructed [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet) object. These must be constructed in JavaScript, but can be generated by helper libraries or custom loaders. If, for example, you like writing your CSS the same file as your element, you can manually create a CSSStyleSheet: |
| 52 | + |
| 53 | +```typescript |
| 54 | +import {controller, style} from '@github/catalyst' |
| 55 | + |
| 56 | +const sheet = new CSSStyleSheet() |
| 57 | +sheet.replaceSync(` |
| 58 | + :host { |
| 59 | + display: flex |
| 60 | + } |
| 61 | +`) |
| 62 | + |
| 63 | +@controller |
| 64 | +class UserRow extends HTMLElement { |
| 65 | + @style componentCSS = sheet |
| 66 | + |
| 67 | + connectedCallback() { |
| 68 | + this.attachShadow({ mode: 'open' }) |
| 69 | + } |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +Alternatively you can import one, as long as the return value is a [Constructable CSSStyleSheet](https://web.dev/constructable-stylesheets/): |
| 74 | + |
| 75 | +```typescript |
| 76 | +import {controller, style} from '@github/catalyst' |
| 77 | +import {css} from '@acme/cool-css' |
| 78 | + |
| 79 | +@controller |
| 80 | +class UserRow extends HTMLElement { |
| 81 | + @style componentCSS = css` |
| 82 | + :host { |
| 83 | + display: flex |
| 84 | + } |
| 85 | + ` |
| 86 | + |
| 87 | + connectedCallback() { |
| 88 | + this.attachShadow({ mode: 'open' }) |
| 89 | + console.assert(this.componentCSS instanceof CSSStyleSheet) |
| 90 | + } |
| 91 | +} |
| 92 | +``` |
0 commit comments