Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Declarative CSS Modules and Declarative Shadow DOM adoptedstylesheets attribute #1000

Closed
1 task done
KurtCattiSchmidt opened this issue Oct 1, 2024 · 7 comments
Closed
1 task done
Assignees
Labels
Mode: breakout Work done during a time-limited breakout session Resolution: satisfied with concerns The TAG is satisfied with this work overall but requires changes Review type: CG early review An early review of general direction from a Community Group Topic: components Topic: CSS Venue: WHATWG

Comments

@KurtCattiSchmidt
Copy link

こんにちは 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 jyasskin added Venue: WHATWG Review type: CG early review An early review of general direction from a Community Group Topic: CSS Topic: components Mode: breakout Work done during a time-limited breakout session and removed Progress: untriaged labels Oct 2, 2024
@LeaVerou LeaVerou self-assigned this Oct 8, 2024
@torgo torgo added this to the 2024-10-14-week milestone Oct 9, 2024
@jyasskin
Copy link
Contributor

jyasskin commented Oct 23, 2024

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
Copy link

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
Copy link
Contributor

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>.

@plinss
Copy link
Member

plinss commented Oct 29, 2024

A concern about whatever mechanism is used here is that there is an existing behavior of copy-on-write behavior when the same stylesheet is loaded from multiple places. e.g. if I <link> a.css twice, there's one instanace in RAM, but if it's modified via CSSOM, it splits into two instances so page authors can't tell it was shared in the first place.

However, with stylesheets that are adopted via JS API, the same instance is re-used and changes to that instance are reflected in each place they are referenced.

At the least we need to be clear what the expected behavior will be when declaratively adopting a stylesheet. It's also worth thinking about either reconciling the behavior or giving authors explicit mechanisms to opt-in to the behavior they desire.

@martinthomson
Copy link
Contributor

(As you can tell, this is a real team effort :)

We're happy to see this feature progress. There are a few things that we've identified in the comments above that need to be considered by the working group as you continue to develop the feature. Closing the early review as "satisfied with concerns" to reflect that.

@phumai98
Copy link

phumai98 commented Oct 31, 2024

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?

The example in the explainer refers to the CSS @import rule, while I think you are referring to JS import? @jyasskin

@LeaVerou
Copy link
Member

LeaVerou commented Nov 1, 2024

The example in the explainer refers to the CSS @import rule, while I think you are referring to JS import? @jyasskin

No, I was not referring to a JS import. I was referring to a CSS @import in Shadow DOM, which is what the claim was about. I suspect that whoever thought it was not possible must have tried it with the wrong URL — I do recall some weirdness around how relative URLs are resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Mode: breakout Work done during a time-limited breakout session Resolution: satisfied with concerns The TAG is satisfied with this work overall but requires changes Review type: CG early review An early review of general direction from a Community Group Topic: components Topic: CSS Venue: WHATWG
Projects
None yet
Development

No branches or pull requests

9 participants