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

CSS module support #46689

Open
5 tasks done
justinfagnani opened this issue Nov 4, 2021 · 25 comments
Open
5 tasks done

CSS module support #46689

justinfagnani opened this issue Nov 4, 2021 · 25 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@justinfagnani
Copy link

justinfagnani commented Nov 4, 2021

Suggestion

Now that TS 4.5 supports import assertions and JSON modules, it'd be great if it similarly supported CSS modules which are now shipping in Chrome and Edge.

There are two aspects of JSON module support that would be important to add for CSS modules:

  1. Built-in typing of CSS modules based on their import assertion. This could be done in library code with Ambient Module Declarations for Import Assertions #46135 but since there's a specified interface of CSS modules, the type would ideally be included in TS's DOM lib.
  2. Copying of CSS files during build. JSON files are copied as part of compilation so that relative paths to JSON modules work in the compiled output. Doing this for CSS modules would ensure that they also work in the output without an extra copy step.

🔍 Search Terms

  • CSS module

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

📃 Motivating Example

import styles from './styles.css' assert {type: 'css'};
document.adoptedStyleSheets = [...document.adoptedStyleSheets, styles];

💻 Use Cases

Importing standard CSS modules...

@benjamind
Copy link

This would indeed simplify a lot of build processes that we have on Adobe projects. Right now this is all handled out of band by additional build steps, or bundler plugins.

@andrewbranch andrewbranch added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Nov 4, 2021
@freshp86
Copy link

freshp86 commented May 2, 2022

Any updates here?

@JustFly1984
Copy link

+1

@mhoad
Copy link

mhoad commented Jul 13, 2022

@andrewbranch just wondering what kind of feedback you might be looking for on this issue in order to help with this?

@franktopel
Copy link

Another 5 months in, what's the state of this?

@andrewbranch
Copy link
Member

Well, the 52 👍 on the issue are a good signal. Let’s start here:

which are now shipping in Chrome and Edge.

After a year, has anything changed here? Any other major browsers shipping? Any significant changes to the proposal? What does the process for proposals here moving into a spec or standard look like? Any progress on that?

@thescientist13
Copy link

thescientist13 commented Oct 25, 2022

The precursor to CSS Modules is Constructable Stylesheets which in the past year have been shipped by Firefox and is now available in Safari Technical Preview. 🎉

That said, I don't think FF has shipped Import Assertions yet and Safari still has CSS Module Scripts in open status.

But they are all coming along quickly!

@justinfagnani
Copy link
Author

justinfagnani commented Oct 25, 2022

@andrewbranch CSS Module Scripts, along with JSON Module Scripts, are merged into the HTML specification: https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script

As mentioned by @thescientist13, Constructible StyleSheets is a prerequisite and is now implemented in all major browsers.

Firefox also has a positive response to CSS Modules Scripts on their standard position issue. Webkit has listed a single concern about CSP integration (but this is just a decision that needs to be made, not a risk).

Given that Chrome, Edge, Safari and Firefox were all very involved in the CSS Module Scripts discussion, including specs that build up to it like import assertions, constructible stylesheets, adopted stylesheets, and modifications to JS module records, I'm personally very confident that this will ship in all browser, and relatively soon at the pace that they're moving.

@justinfagnani
Copy link
Author

@andrewbranch also, fixing #46135 first is an option that would give us the ability to type CSS Module Scripts correctly, like so:

declare module '*' assert {type: 'css'} {
  const stylesheet: CSSStyleSheet;
  export default stylesheet;
}

@JustFly1984
Copy link

JustFly1984 commented Nov 11, 2022

Currently I use Typed CSS Modules VSCode extension to generate d.ts files for each css/scss file. It helps a lot to find undefined classnames and fails build if somebody removes used classname from css/scss.
The way how css/scss type declaration is used in create-react-app is a crime, cos it just provides a Record<string, string>, which defaults any classname to valid string, even if it does not exists.

It could be nice if classnames, scss variables and other selectors could be inferred automatically without the need to generate d.ts files.

@justinfagnani
Copy link
Author

@JustFly1984 this is about typing support for the HTML-standard CSS module scripts, which are already supported in some browsers. They simply default export a CSSStyleSheet, and the feature request is to type assert {type: 'css'} modules as doing that.

Userland CSS module systems will need their own support for their semantics, and presumably already have such systems in their toolchains.

@franktopel
Copy link

franktopel commented Dec 12, 2022

@justinfagnani

Not that TS 4.5 support import assertions and JSON modules [...]

Was that rather supposed to be

Now that TS 4.5 supports import assertions and JSON modules [...]

?

@bivens-dev
Copy link

@andrewbranch not sure if you're the best person to ping about this but as far as I can tell this is now officially part of the HTML spec https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script and is now natively supported in a number of browsers and has full cross browser support thanks to this https://github.com/guybedford/es-module-shims

Would it make sense to revisit this perhaps?

@andrewbranch
Copy link
Member

It would, except that import assertions were demoted to Stage 2, so for sure nothing that depends on them is happening in TypeScript right now.

@justinfagnani
Copy link
Author

They're not going to be removed though, and the current spec change keeps the assert keyword and the rest of the syntax. The change is mostly about semantics. TypeScript already supports the syntax, and this spec change would allow imports to be used to affect the import like how resolution-mode does. That was previously in violation of the spec and would now be compliant.

I've been using CSS Modules with recently with this snippet:

declare module '*' assert {type: 'css'} {
  const stylesheet: CSSStyleSheet;
  export default stylesheet;
}

And one big problem is that TypeScript doesn't attempt to understand the specifiers as actual file paths, so we don't get jump-to-definition on the import or specifier. It seem like treating the specifier more or less normal and trying to resolve it on disk would be a low-risk change that would be helpful for non-standard imports too.

@andrewbranch
Copy link
Member

My understanding is that there’s a possibility that the proposal will come back with identical syntax and changed semantics, or might come back with alternative syntax (like with), potentially leaving assert in place as an Annex B scar, or something. I’m hopeful it will get worked out soon in a way that gives us a clear path forward both on this and on resolution-mode, but expanding our feature set of import assertions now based only on that hope seems like a bad idea. If they had never reached Stage 3, they would not be in the WHATWG spec nor in TypeScript. This is a rare situation, but since they are not in Stage 3+ now, we’re basically just going to pretend they’re not in the product until this gets worked out at TC39.

@freshp86
Copy link

freshp86 commented Jun 1, 2023

It would, except that import assertions were demoted to Stage 2, so for sure nothing that depends on them is happening in TypeScript right now.

According to https://github.com/tc39/proposal-import-attributes#history the proposal moved back to Stage3, pasting relevant entry below (emphasis mine)

2023-03: The proposal is renamed to Import attributes and moves back to Stage 3 (TODO: notes, slides). The restriction on the cache key is completely removed, and the keyword changes back from assert to with: import { x } from "./mod" with { type: "json" };. For compatibility with existing implementations, the assert keyword will still be supported until it's safe to remove it, if it will ever be.

See commit from March 31st which updated he README file.

My understanding is that there’s a possibility that the proposal will come back with identical syntax and changed semantics, or might come back with alternative syntax (like with), potentially leaving assert in place as an Annex B scar, or something

This is also addressed in the update linked above.

Is the above a good enough signal for unblocking adding TypeScript compiler support for this feature? Thanks!

@andrewbranch
Copy link
Member

Import attributes achieved conditional Stage 3 and the last bits of making it official are still outstanding. Please follow:

@justinfagnani
Copy link
Author

It looks like import attributes support is going to ship in 5.3 🎉

Can CSS modules get another look to bring them up to parity with JSON modules?

@justinfagnani
Copy link
Author

@andrewbranch an update on your question

After a year, has anything changed here? Any other major browsers shipping? Any significant changes to the proposal? What does the process for proposals here moving into a spec or standard look like? Any progress on that?

Gecko and Webkit still haven't implemented CSS module scripts, but they have implemented Constructible Stylesheets and import attributes, which are the prerequisites. They still have positive support on their standards positions issues, and there's a request to add import attributes, and JSON and CSS module scripts to interop 2024.

@koba-ninkigumi
Copy link

koba-ninkigumi commented Nov 12, 2023

Is there a minimum working sample of a css module script (import attributes) using TypeScript 5.3?

My this stackblitz sample fails to compile this code in TypeScript 5.3.

const css = await import(cssfile, { with: { type: 'css' } });
if (this.shadowRoot !== null) {
  this.shadowRoot.adoptedStyleSheets = [css]
}

Of course, this stackblitz samples using fetch still work fine today.

const cssstring = await (await fetch(cssfile)).text()
const css = new CSSStyleSheet()
css.replaceSync(cssstring)
if (this.shadowRoot !== null) {
  this.shadowRoot.adoptedStyleSheets = [css]
}

@mark-dropbear
Copy link

@andrewbranch I just wanted to re-ping on this topic if possible to see what roadblocks still remain? This is having an awful impact on my workflows for the last year or so and as far as I can tell all of the blockers you had previously mentioned were since resolved.

@andrewbranch
Copy link
Member

See #56359 and #46135. There are no blockers per se but when I tried to move this along there were a lot of unanswered questions and design work to be done. The most useful thing right now would be for you to explain your use cases and workarounds fully.

@justinfagnani
Copy link
Author

@andrewbranch I'm taking a look at #56359, would it be best for me to give my answer to those questions in #46135 ?

@andrewbranch
Copy link
Member

Yes, I think so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests