w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
332 stars 56 forks source link

Declarative CSS Modules and Declarative Shadow DOM `adoptedstylesheets` attribute #1000

Open KurtCattiSchmidt opened 3 weeks ago

KurtCattiSchmidt commented 3 weeks ago

こんにちは TAG-さん!

I'm requesting an early TAG design review of Declarative CSS Modules and the Declarative Shadow DOM adoptedstylesheets attribute.

When developing web components, web authors often encounter challenges with distributing global styles into shadow roots and sharing styles across different shadow roots. Declarative shadow DOM (DSD) enables creation of shadow DOM without JS, but adding styles to DSD requires the developer to either use JS to put a shared stylesheet into adoptedStyleSheets, or to duplicate the styles in a <style> element for each component instance.

We propose an enhancement to CSS module scripts that would allow developers to create CSS module scripts declaratively without a network request, and apply them to DSDs without the use of JS.

Further details:

jyasskin commented 4 days ago

We reviewed this today in a breakout and while we agree that this use case needs to be solved, we think there might be a way to tweak or to finish implementing some more-general features to solve the use cases, so that we wouldn't need to add features that are specific to web components.

It seems that this is solving two problems:

  1. Sharing of styles across shadow roots
  2. Defining those styles inline in the containing HTML file

For the first problem, the reasoning listed for why <link> or @import cannot be used for sharing styles across shadow roots is simply that they cause additional network requests. Minimizing network requests also seems to be the core of the reason to use ESM-style CSS imports.

In that case, perhaps the issue can be addressed at the root, by specifying that these requests MUST be deduplicated, either by default (if web compatible) or with a certain flag set. It appears that in most cases UAs deduplicate these anyway, and in cases where they don't, that's not consistent (e.g. @Westbrook shared https://q9yc7v.csb.app/ which causes multiple requests in Chrome but not in Safari), which is encouraging in terms of web compat. Fixing the underlying problem benefits not just web components, but the entire platform at large.

Btw it's incorrect to say that

Inline <style> blocks do not support @import rules

@LeaVerou has personally used inline <style> with @import rules regularly, even in shadow roots (see https://elements.colorjs.io/src/color-picker/). Are you talking about a more specific case they don't work with? E.g. constructible or adopted stylesheets?

To allow these styles to be defined inline, @sheet seems like a better solution. Using <script> for CSS, with specifiers that mimic filenames, seems like a disproportionate level of complexity for the problem being solved, and contorts existing primitives into doing things they were never meant to do. That is, adoptedStylesheets="sheet1, sheet2" seems better than adoptedStylesheets="/invented_filename1.css, /invented_filename2.css". The main drawback listed in the explainer for @sheet is lack of implementations, which seems moot given this is also not implemented?

Westbrook commented 4 days ago

The idea of ensuring <link> and @import do deduplication is awesome! This should be done, regardless. 👏🏼 👏🏼 👏🏼

While they are doing so, will it be possible to ensure deduplication of that same content when the subsequent request is made in the form of import style from './style.css' with { type: 'css' };? This is likely the secondary request when some styles are handled in HTML and some are handled in JS whether that JS is powering shadow DOM scoped styles or CSS-in-JS solutions.

As part of your breakout, where there any suggestions as to how leveraging these existing APIs in this way could prevent additional network requests at large, or more directly contend with the proposal's approach to inlining the CSS in the initial HTML response?

jyasskin commented 4 days ago

I think resource fetching ought to be deduplicated between all of <link>, <style src>, CSS @import, and JS import, unless that's not web-compatible for some reason.

We thought the existing @sheet design made sense as the way to inline style in the HTML response without immediately applying it to the page. There was some discussion about whether the platform might be able to avoid adding the adoptedStylesheets attribute and instead somehow use <link rel=stylesheet href="#sheetName">, but none of the obvious ways to do that (e.g. <style id=sheetName some-attribute-that-prevents-immediate-application> or <script type=text/css id=sheetName>) seemed clearly better than adding the attribute to <template>.