Skip to content

A toolkit for making CSS Modules useful.

License

Notifications You must be signed in to change notification settings

mizdra/css-modules-kit

Repository files navigation

CSS Modules Kit

A toolkit for making CSS Modules useful.

Logo

Intro

By default, CSS Modules have limited language features in editors. For example:

  • Clicking on styles.button does not "Go to Definition" in Button.module.css.
  • Renaming styles.button modifies the code in Button.tsx but not in Button.module.css.
  • Performing "Find All References" for styles.button finds references in Button.tsx, not in Button.module.css.

It has been difficult to solve these issues because the TypeScript Language Server (tsserver) does not load CSS files. TSServer does not know which part of the code to "Go to Definition" for, nor which part of the code to rename.

CSS Modules Kit solves this problem by using the TypeScript Language Service Plugin and Volar.js. They extend tsserver to load *.module.css files. As a result, rich language features become available. Moreover, it works with various editors.

In addition, CSS Modules Kit provides various tools for CSS Modules (e.g., codegen, linter-plugin). CSS Modules Kit provides you everything you need. It saves you from the hassle of combining multiple third-party tools.

Get Started

See docs/get-started.md.

Playground

  1. Open https://stackblitz.com/~/github.com/mizdra/css-modules-kit-example
  2. After waiting a moment, a message will appear in the bottom-right saying you want to install the recommended extensions. Click Install and wait for the installation to complete.
  3. Open src/a.tsx. CSS Modules language features should now be enabled.

Available Tools

Supported Language Features

Go to Definition
2024-12-22.2.05.16.mov
Rename Symbol
2024-12-22.2.13.35.mov
Find All References
2024-12-22.2.10.01.mov
Definition Preview by Hover

You can preview the definition with Command + Hover on macOS and VS Code (key bindings may vary depending on your OS and editor).

2025-06-16.0.25.40.mov
Automatically update import statements when moving `*.module.css`
2024-12-26.20.24.48.mov
Create CSS Module file for current file

If there is no CSS Module file corresponding to xxx.tsx, create one.

2025-02-02.19.07.06.mov
Complete `className={...}` instead of `className="..."`

In projects where CSS Modules are used, the element is styled with className={styles.xxx}. However, when you type className, className="..." is completed. This is annoying to the user.

Therefore, instead of completing className="...", it should complete className={...}.

2025-02-02.19.07.27.mov
Prioritize the `styles' import for the current component file

When you request styles completion, the CSS Module file styles will be suggested. If there are many CSS Module files in the project, more items will be suggested. This can be confusing to the user.

So I have made it so that the styles of the CSS Module file corresponding to the current file is shown first.

image
Add missing CSS rule

If you are trying to use a class name that is not defined, you can add it with Quick Fixes.

2025-02-02.19.24.36.mov

Configuration

css-modules-kit uses tsconfig.json as its configuration file. This configuration only affects the ts-plugin and codegen.

cmkOptions.enabled

Type: boolean, Default: true

Enables or disables css-modules-kit. When set to false, codegen will exit with an error. Currently, both codegen and the ts-plugin will work even if this option is omitted, but in the future, they will not work unless this option is set to true. For more details, see #289.

{
  "compilerOptions": {
    // ...
  },
  "cmkOptions": {
    "enabled": true,
  },
}

cmkOptions.dtsOutDir

Type: string, Default: "generated"

Specifies the directory where *.d.ts files are output.

{
  "compilerOptions": {
    // ...
  },
  "cmkOptions": {
    "dtsOutDir": "generated/cmk",
  },
}

cmkOptions.arbitraryExtensions

Type: boolean, Default: false

Determines whether to generate *.module.d.css.ts instead of *.module.css.d.ts.

{
  "compilerOptions": {
    // ...
  },
  "cmkOptions": {
    "arbitraryExtensions": true,
  },
}

cmkOptions.namedExports

Type: boolean, Default: false

Determines whether to generate named exports in the d.ts file instead of a default export.

{
  "compilerOptions": {
    // ...
  },
  "cmkOptions": {
    "namedExports": true,
  },
}

cmkOptions.prioritizeNamedImports

Type: boolean, Default: false

Whether to prioritize named imports over namespace imports when adding import statements. This option only takes effect when cmkOptions.namedExports is true.

When this option is true, import { button } from '...' will be added. When this option is false, import button from '...' will be added.

{
  "compilerOptions": {
    // ...
  },
  "cmkOptions": {
    "namedExports": true,
    "prioritizeNamedImports": true,
  },
}

cmkOptions.keyframes

Type: boolean, Default: true

Determines whether to generate the token of keyframes in the d.ts file.

{
  "compilerOptions": {
    // ...
  },
  "cmkOptions": {
    "keyframes": false,
  },
}

Limitations

Due to implementation constraints and technical reasons, css-modules-kit has various limitations.

  • Sass and Less are not supported.
    • If you want to use Sass and Less, please use happy-css-modules. Although it does not offer as rich language features as css-modules-kit, it provides basic features such as code completion and Go to Definition.
  • The name of classes, @value, and @keyframes must be valid JavaScript identifiers.
    • For example, .fooBar and .foo_bar are supported, but .foo-bar is not supported.
    • See #176 for more details.
  • The specifiers in @import '<specifier>' and @value ... from '<specifier>' are resolved according to TypeScript's module resolution method.
  • :local .foo {...} is not supported.
    • Use :local(.foo) {...} instead.
  • :global .foo {...} is not supported.
    • Use :global(.foo) {...} instead.
  • @keyframes :local(foo) {...} is not supported.
    • Use @keyframes foo {...} instead.
    • Meanwhile, @keyframes :global(foo) { ... } is supported.
  • VS Code for Web is not supported.

Comparison

Viijay-Kr/react-ts-css also provides rich language features for CSS Modules. However, it is implemented using the VS Code Extension API. Therefore, it only supports VS Code.

On the other hand, css-modules-kit is implemented using the TypeScript Language Service Plugin. It is a technology that does not depend on the editor. css-modules-kit supports editors other than VS Code.

mrmckeb/typescript-plugin-css-modules is also implemented using the TypeScript Language Service Plugin. However, it only supports basic language features such as completion, typed styles, and Go to Definition. Cross-file language features between *.tsx and .module.css—such as Rename and Find All References—are not supported.

This is because mrmckeb/typescript-plugin-css-modules does not extend tsserver to handle *.module.css files. Due to the lack of information about *.module.css files, tsserver cannot provide cross-file language features between *.tsx and .module.css.

On the other hand, css-modules-kit extends tsserver to handle *.module.css files. The extension is realized by Volar.js. Please read the following slides for details (in Japanese).

About

A toolkit for making CSS Modules useful.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 7

Languages