Skip to content

Commit 5be5ab0

Browse files
Add comparisons between LRLR and Declarative CSS Modules (#1073)
This change updates both the LRLR and Declarative CSS Modules explainers to cover differences between them in preparation for a TAG discussion.
1 parent e983ef5 commit 5be5ab0

File tree

2 files changed

+128
-32
lines changed

2 files changed

+128
-32
lines changed

LocalReferenceLinkRel/explainer.md

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ elements.
5959

6060
- Anything specific to `@sheet` should be discussed in its dedicated
6161
<a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/AtSheet/explainer.md">proposal</a>.
62-
- Modifications to Shadow DOM scoping behaviors. This proposal depends on
63-
existing Shadow DOM behavior as currently defined. Styles defined in a Shadow
64-
DOM will remain inaccessible to the Light DOM and other Shadow DOMs.
6562

6663
## Proposal - Local References for Link Rel Tags
6764

@@ -148,6 +145,85 @@ the shadow root where they are defined, as illustrated by the following examples
148145
Styles defined inside the sibling Shadow Root are not applied, so "Inside Sibling Shadow DOM" is not blue.
149146
</p>
150147

148+
In contrast to this proposal, [Declarative CSS Modules](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/ShadowDOM/explainer.md) always have global scope. Shadow DOM scoping could be modified though other means, as discussed
149+
in [this thread](https://github.com/whatwg/html/issues/11364). All of the suggestions in that thread would
150+
allow for this feature to work with any shadow root, regardless of scope.
151+
152+
For example, the "Referencetarget inspired solution on `<template>`" would work with this feature as follows:
153+
154+
```html
155+
<template exportids="foo"><!-- Exports 'foo' to the light DOM -->
156+
<template exportids="foo, bar">
157+
<style id="foo">
158+
...
159+
</style>
160+
<style id="bar">
161+
...
162+
</style>
163+
</template>
164+
<link rel="stylesheet" href="#bar"> <!-- 'bar' is in scope due to `exportids` -->
165+
</template>
166+
<link rel="stylesheet" href="#foo"><!-- 'foo' is in the global scope, reference matched -->
167+
<link rel="stylesheet" href="#bar"><!-- 'bar' is not in scope, reference not matched -->
168+
```
169+
170+
The other examples in https://github.com/whatwg/html/issues/11364 also use this proposal as an example
171+
of how scoping can be expanded for Shadow DOM elements.
172+
173+
### Key Differences Between This Proposal And Declarative CSS Modules
174+
175+
Both this proposal and [Declarative CSS Modules](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/ShadowDOM/explainer.md)
176+
allow authors to share inline CSS with Shadow Roots. There are some key differences in both syntax and
177+
behaviors, as illustrated in the following table:
178+
179+
| | Local Reference Link Rel | Declarative CSS Modules |
180+
| :---: | :---: | :---: |
181+
| Scope | ⚠️ [Standard DOM scoping](#Scoping) | Global scope |
182+
| Identifier syntax | Standard HTML IDREF | Module identifier |
183+
| Attribute used | Standard HTML `href` | New attribute for `identifier` |
184+
| Uses existing HTML concepts | ✅ Yes | ❌ No |
185+
| Uses existing module concepts | ❌ No | ✅ Yes |
186+
| Extensibility | Clean @sheet integration, scope expansion could apply to SVG references | More declarative module types (HTML, SVG, etc.) |
187+
188+
### Extensibility
189+
190+
This proposal works nicely with CSS `@sheet`, allowing for the Light DOM to define styles that
191+
only apply to selected Shadow DOM elements, as demonstrated by the following example:
192+
193+
```html
194+
<style id="inline_styles">
195+
@sheet my_sheet {
196+
p {
197+
color: blue;
198+
}
199+
}
200+
</style>
201+
<p>"my_sheet" isn't imported into the light DOM, so this isn't blue</p>
202+
<template shadowrootmode="open">
203+
<link rel="stylesheet" href="#inline_styles" sheet="my_sheet" />
204+
<p>Inside Shadow DOM - "my_sheet" was included so this text is blue!</p>
205+
</template>
206+
```
207+
208+
All of proposals mentioned in https://github.com/whatwg/html/issues/11364 would not only benefit this
209+
feature - SVG references, local anchors, and anything that takes an IDREF would benefit. For instance, SVG could benefit with this scoping extension as follows:
210+
211+
```html
212+
<template exportids="foo"><!-- Exports 'foo' to the light DOM -->
213+
<template exportids="foo">
214+
<svg height="100" width="100">
215+
<circle id="foo" r="45" cx="50" cy="50" fill="red" />
216+
</svg>
217+
</template>
218+
<svg height="100" width="100">
219+
<use href="#foo" /><!-- "foo" is in this shadow scope due to the "exportids" attribute above -->
220+
</svg>
221+
</template>
222+
<svg height="100" width="100">
223+
<use href="#foo" /><!-- "foo" is in the Light DOM scope due to the "exportids" attribute above -->
224+
</svg>
225+
```
226+
151227
### Fetch Behavior
152228

153229
In user agents where the Local References In `<link>` Tags feature is not

ShadowDOM/explainer.md

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -205,43 +205,43 @@ Global styles can be included in a single stylesheet, which is then importable i
205205
## Proposal: Inline, declarative CSS module scripts
206206
This proposal builds on [CSS module scripts](https://web.dev/articles/css-module-scripts), enabling authors to declare a CSS module inline in an HTML file and link it to a DSD using its [module specifier](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#:~:text=The-,module%20specifier,-provides%20a%20string). A `type=”css-module”` attribute on the `<script>` element would define it as a CSS module script and the specifier attribute would add it to the module cache as if it had been imported. This allows the page to render with the necessary CSS modules attached to the correct scopes without needing to load them multiple times. Note that module maps are global, meaning that modules defined in a Shadow DOM will be accessible throughout the document context.
207207
```js
208-
<script type="css-module" specifier="/foo.css">
208+
<style type="css-module" specifier="foo">
209209
#content {
210210
color: red;
211211
}
212-
</script>
212+
</style>
213213
```
214-
Given this `<script>` tag, the styles could be applied to a DSD as follows:
214+
Given this `<style>` tag, the styles could be applied to a DSD as follows:
215215
```html
216216
<my-element>
217-
<template shadowrootmode="open" adoptedstylesheets="/foo.css">
217+
<template shadowrootmode="open" adoptedstylesheets="foo">
218218
<!-- ... -->
219219
</template>
220220
</my-element>
221221
```
222222

223-
The shadow root will be created with its `adoptedStyleSheets` containing the `"/foo.css"` CSS module script’s CSSStyleSheet instance. This single `CSSStyleSheet` instance can be shared by any number of shadow roots.
223+
The shadow root will be created with its `adoptedStyleSheets` containing the `"foo"` CSS module script’s `CSSStyleSheet` instance. This single `CSSStyleSheet` instance can be shared by any number of shadow roots.
224224

225225
An inline CSS module script could also be imported in a JavaScript module in the usual way:
226226
```html
227227
import styles from '/foo.css' with { type: 'css' };
228228
```
229229
Another advantage of this proposal is that it can allow multiple module specifiers in the `adoptedstylesheets` property:
230230
```html
231-
<script type="css-module" specifier="/foo.css">
231+
<style type="css-module" specifier="foo">
232232
#content {
233233
color: red;
234234
}
235-
</script>
235+
</style>
236236

237-
<script type="css-module" specifier="/bar.css">
237+
<style type="css-module" specifier="bar">
238238
#content {
239239
font-family: sans-serif;
240240
}
241-
</script>
241+
</style>
242242

243243
<my-element>
244-
<template shadowrootmode="open" adoptedstylesheets="/foo.css, /bar.css">
244+
<template shadowrootmode="open" adoptedstylesheets="foo, bar">
245245
<!-- ... -->
246246
</template>
247247
</my-element>
@@ -255,24 +255,7 @@ A global map does come with some tradeoffs, particularly when names collide. Wit
255255

256256
### `<script>` vs `<style>` For CSS Modules
257257

258-
This document uses the `<script>` tag for defining CSS Modules. Developer feedback has shown a preference for using the `<style>` tag when defining a CSS Module. This makes sense for CSS Modules in isolation, but does not align with other types of modules. The table in the [next section](#other-declarative-modules) details other module types and demonstrates the degree of consistency achieved with `<script>`. Developer feedback is important and should be considered, even at the potential expense of consistency.
259-
260-
This is an example of a CSS Module defined with the `<style>` tag:
261-
```html
262-
<style type="css-module" specifier="/foo.css">
263-
#content {
264-
color: red;
265-
}
266-
</style>
267-
268-
<my-element>
269-
<template shadowrootmode="open" adoptedstylesheets="/foo.css">
270-
<!-- ... -->
271-
</template>
272-
</my-element>
273-
```
274-
275-
A compromise could be to support both `<script>` tags and `<style>` tags.
258+
Earlier versions of this document used the `<script>` tag for declaring CSS Modules. Developer feedback has shown a strong preference for using the `<style>` tag when declaring CSS Modules, so this proposal has been updated accordingly. The `<script>` tag remains a more natural wrapper for [other declarative modules](#other-declarative-modules).
276259

277260
### Behavior with script disabled
278261

@@ -318,13 +301,50 @@ CSS Modules are not the only type of module - there are also JavasScript, JSON,
318301
| Module type | Script Module | Declarative Module |
319302
| -------------- | -------------------------------------------------------- | --------------------------------------------------------------------------|
320303
| JavaScript | `import { foo } from "./bar.js";` | `<script type="script-module" specifier="/bar.js"></script>` |
321-
| CSS | `import foo from "./bar.css" with { type: "css" };` | `<script type="css-module" specifier="/bar.css"></script>` |
304+
| CSS | `import foo from "./bar.css" with { type: "css" };` | `<style type="css-module" specifier="bar"></style>` |
322305
| JSON | `import foo from "./bar.json" with { type: "json" };` | `<script type="json-module" specifier="/bar.json"></script>` |
323306
| HTML | `import {foo} from "bar.html" with {type: "html"};` | `<script type="html-module" specifier="/bar.html"></script>` |
324307
| SVG | `import {foo} from "bar.svg" with {type: "svg"};` | `<script type="svg-module" specifier="/bar.svg"></script>` |
325308
| WASM | `import {foo} from "bar.wasm" with {type: "wasm"};` | `<script type="wasm-module" specifier="/bar.wasm"></script>` |
326309

327310
## Alternate proposals
311+
312+
### [Local References For Link Rel](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/LocalReferenceLinkRel/explainer.md)
313+
314+
This proposal extends the existing `<link>` tag to support local `<style>` tag references as follows:
315+
316+
```html
317+
<style id="inline_styles">
318+
p {
319+
color: blue;
320+
}
321+
</style>
322+
<p>Outside Shadow DOM</p>
323+
<template shadowrootmode="open">
324+
<link rel="stylesheet" href="#inline_styles" />
325+
<p>Inside Shadow DOM</p>
326+
</template>
327+
```
328+
329+
This allows for sharing styles defined in the Light DOM across Shadow Roots. Due to scoping behaviors, it will not allow for styles defined in a Shadow DOM
330+
to be accessed in any other Shadow Root. This limitation could be addressed with extensions on Shadow DOM scoping suggested in
331+
[this thread](https://github.com/whatwg/html/issues/11364).
332+
333+
### Key Differences Between This Proposal And Local References For Link Rel
334+
335+
Both this proposal and [Local References For Link Rel](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/LocalReferenceLinkRel/explainer.md)
336+
allow authors to share inline CSS with Shadow Roots. There are some key differences in both syntax and
337+
behaviors, as illustrated in the following table:
338+
339+
| | Local Reference Link Rel | Declarative CSS Modules |
340+
| :---: | :---: | :---: |
341+
| Scope | ⚠️ [Standard DOM scoping](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/LocalReferenceLinkRel/explainer.md#Scoping) | Global scope |
342+
| Identifier syntax | Standard HTML IDREF | Module identifier |
343+
| Attribute used | Standard HTML `href` | New attribute for `identifier` |
344+
| Uses existing HTML concepts | ✅ Yes | ❌ No |
345+
| Uses existing module concepts | ❌ No | ✅ Yes |
346+
| Extensibility | Clean @sheet integration, scope expansion could apply to SVG references | More declarative module types (HTML, SVG, etc.) |
347+
328348
### [Layer and adoptStyles](https://github.com/w3c/csswg-drafts/issues/10176#proposal)
329349
This proposal adds the `adoptStyles` attribute to the template element, enabling its shadow root to adopt styles from outside of the shadow DOM.
330350

0 commit comments

Comments
 (0)