- From: Kurt Catti-Schmidt via GitHub <sysbot+gh@w3.org>
- Date: Mon, 03 Feb 2025 23:47:41 +0000
- To: public-css-archive@w3.org
> Good proposal 👍 Thank you for raising this! Glad you like it! 👍 I appreciate your thoughts and suggestions and took some time going over them. > > `@sheet` represents an inlined `.css` file, right? So shouldn't this match `@import` in as many ways as possible? They should be equivalent and there shouldn't be syntactic benefits or drawbacks to either. You're correct that `@sheet` has a lot of similarities with `@import`, in particular that they both bring in style rules from a separate file, but the real power of `@sheet` is that it binds a set of rules to an identifier that can be imported in contexts beyond CSS. This identifier is really important, as it allows `@sheet` blocks to be imported in different contexts (e.g. `<link rel>`, `@import`, and CSS Modules). Conceptually, you can think of each `@sheet` block as a separate CSS file that gets represented by its `@sheet` identifier instead of a file name. > > With that in mind I think that nesting should be allowed and that using `@import` in `@sheet` should also be allowed. > > These should all be equivalent: > > 1: > > `index.css` > > @sheet foo { > @sheet bar {} > } If this were to be referenced by a `<link rel>` tag, how would you target `bar`? We could differentiate nested sheets with some sort of delimiter (e.g. if we used `#` to delimit between nested sheets this could be valid - `<link rel="stylesheet" href="index.css" sheet="foo#bar">`), but I am struggling to come up with a use case. What types of situations would nested `@sheet` definitions enable? > 2: > > `index.css` > > @sheet foo { > @import "bar.css"; > } This seems valid to me. I know that there are rules around `@import` that we'd need to respect, but I think `@import` should be able to work as the first / only statement of an `@sheet`. > 3: > > `index.css` > > @import "foo.css"; > `foo.css` > > @import "bar.css"; > Is there a reason we can't do this? This looks valid to me too. > > I agree that for the order `@sheet` should be valid anywhere `@import` is. > > `<link rel="stylesheet" href="style.css#sheet1"` is this web compatible? Might need a use counter to check if fragments in stylesheet urls aren't already in use. > The CSSWG decided at the F2F last week to not go with URL fragments for binding to `@sheet` identifiers, so we're now looking into adding an attribute to `<link>` tags to specify which sheet is being imported as well as adding an optional identifier to `@import` for similar functionality there (e.g. `@import sheet1 from "style.css";`). > I know that current frameworks (vite? or vue?) already use this. > That's great context, I appreciate it! > Anonymous sheets should also be supported. > > @sheet {} > Only having named sheets makes it impossible to use this when bundling, despite that being one of the stated goals in the explainer. Could you explain this a bit more? I don't understand how bundling is impossible without anonymous sheets. Also, how could anonymous sheets get applied later? Keep in mind that any rules under an `@sheet` block *don't* get applied by default - they are only applied once they are imported directly by identifier. Without an identifier to be imported later, it seems that these rules would be lost. > > All CSS authors should be able to benefit from this feature, not only those using shadow dom. Most CSS authors will write in multiple files but bundle to avoid a waterfall. They however won't be importing a single sheet. They will want to load and apply everything. > > Having `@sheet` would allow bundlers to avoid other gnarly hacks. Especially when relative imports are mixed with resources loaded from a 3rd party: > > @import "foo.css"; > @import "https://some-framework.com/index.css"; > @import "bar.css"; > The only way to bundle that today is to rewrite as: > > @import url('data:text/css;base64,...'); > @import "https://some-framework.com/index.css"; > @import url('data:text/css;base64,...'); > While with `@sheet` it could be: > > @sheet { /* contents of foo.css */ } > @import "https://some-framework.com/index.css"; > @sheet { /* contents of bar.css */ } > Relative urls have some sharp edges, especially when using in custom props. Typed and untyped custom props also have different behavior. Keep in mind that `@sheet` contents do not apply by default. So for these examples, you *need* an identifier, even if it's throw-away. So your example would look like: ``` @sheet sheet1 { /* contents of foo.css */ } /* Define sheet1 rules */ @import "sheet1"; /* Apply sheet1 rules */ @import "https://some-framework.com/index.css"; @sheet sheet2 { /* contents of bar.css */ } /* Define sheet2 rules */ @import "sheet2"; /* Apply sheet2 rules */ ``` Does that fundamentally change your bundling scenario? Also, is this something existing `@layer` functionality could help with? I appreciate the scenarios you've provided and definitely want to make this feature useful! I don't have a lot of experience with bundling so this is super helpful context. > > Maybe it makes sense to also have a `@base` rule? To match `<base href="https://www.example.com/" />` > > This `@base` rule could be used by CSS authors but is mostly intended to be inserted by bundlers. > > This would allow all relative urls to remain as they were written without any unexpected behavior differences between bundled or unbundled stylesheets. > > Before bundling: > > `https://www.example.com/public/styles/foo.css` `https://www.example.com/public/images/bar.jpg` > > :root { > background: url(../images/bar.jpg); > } > When bundled the relative urls will break unless there is some provision: > > `https://www.example.com/public/index.css` `https://www.example.com/public/images/bar.jpg` > > @sheet { > @base url("https://www.example.com/public/styles/"); > > :root { > background: url(../images/bar.jpg); > } > } > I think it would be ideal if `@sheet` could be used to fully and accurately represent any graph of `@import` statements in a single file. > > Currently the [landscape for CSS bundlers is pretty bleak](https://github.com/romainmenke/css-import-tests?tab=readme-ov-file#current-state). There aren't many tools that actually qualify as CSS bundlers and the most modern offerings don't even work right. > > Having `@sheet` could reduce the number of hacks needed to implement a CSS bundler correctly. Which in turn would make it easier for CSS authors to pick a tool that actually works. These are great suggestions and I really appreciate the perspective from someone who has experience with bundlers! It seems like another use case for some sort of a markup-based equivalent of [import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap), and this is close to it. This seems very useful well beyond `@sheet`, so it might make sense to propose as a separate CSS feature. -- GitHub Notification of comment by KurtCattiSchmidt Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/11509#issuecomment-2632432120 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Monday, 3 February 2025 23:47:42 UTC