> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# output.cssModules

- **Type:** `CSSModules`

Configure custom CSS Modules settings.

The CSS Modules feature in Rsbuild is based on the `modules` option of css-loader. You can refer to [css-loader - modules](https://github.com/webpack/css-loader#modules) to learn more.

## cssModules.auto

The `auto` option enables CSS Modules automatically based on filenames.

- **Type:**

```ts
type Auto =
  | boolean
  | RegExp
  | ((
      resourcePath: string,
      resourceQuery: string,
      resourceFragment: string,
    ) => boolean);
```

- **Default:** `true`

Type descriptions:

- `true`: Enable CSS Modules for all files matching the `/\.module\.\w+$/i.test(filename)` regexp.
- `false`: Disable CSS Modules.
- `RegExp`: Enable CSS Modules for all files matching `/RegExp/i.test(filename)` regexp.
- `function`: Enable CSS Modules for files based on the filename satisfying your filter function check.

For example, to additionally enable CSS Modules for files in the `shared/` directory:

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      auto: (resource) => {
        return resource.includes('.module.') || resource.includes('shared/');
      },
    },
  },
};
```

Another example, to treat all files containing `.module.` and `.modules.` as CSS Modules:

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      auto: /\.modules?\./,
    },
  },
};
```

## cssModules.exportLocalsConvention

Style of exported class names.

- **Type:**

```ts
type CSSModulesLocalsConvention =
  'asIs' | 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly';
```

- **Default:** `'camelCase'`

Type description:

- `asIs`: Class names will be exported as is.
- `camelCase`: Class names will be camelized, the original class name will be exported.
- `camelCaseOnly`: Class names will be camelized, the original class name will not be exported.
- `dashes`: Only dashes in class names will be camelized, the original class name will be exported.
- `dashesOnly`: Dashes in class names will be camelized, the original class name will not be exported.

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      exportLocalsConvention: 'camelCaseOnly',
    },
  },
};
```

### Example

Suppose you have the following CSS file:

```css title="src/style.module.css"
.dash-class {
  color: blue;
}
.camelClass {
  color: red;
}
.underscore_class {
  color: green;
}
```

Different `exportLocalsConvention` configurations will produce different export results:

```js title="src/index.js"
import styles from './style.module.css';

console.log(styles);
// camelCase (default)
// { 'dash-class': '...', 'dashClass': '...', 'camelClass': '...', 'underscore_class': '...', 'underscoreClass': '...' }

// camelCaseOnly
// { 'dashClass': '...', 'camelClass': '...', 'underscoreClass': '...' }

// dashes
// { 'dash-class': '...', 'dashClass': '...', 'camelClass': '...', 'underscore_class': '...' }

// dashesOnly
// { 'dashClass': '...', 'camelClass': '...', 'underscore_class': '...' }

// asIs
// { 'dash-class': '...', 'camelClass': '...', 'underscore_class': '...' }
```

## cssModules.exportGlobals

- **Type:** `boolean`
- **Default:** `false`

Allows exporting names from global class names, so you can use them via import.

### Example

Set the `exportGlobals` to `true`:

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      exportGlobals: true,
    },
  },
};
```

Use `:global()` in CSS Modules:

```css title="style.module.css"
:global(.blue) {
  color: blue;
}

.red {
  color: red;
}
```

Then you can import the class name wrapped with `:global()`:

```tsx title="Button.tsx"
import styles from './style.module.css';

console.log(styles.blue); // 'blue'
console.log(styles.red); // 'red-[hash]'
```

## cssModules.localIdentName

- **Type:** `string`
- **Default:**

```ts
// isProd indicates that the production build
const localIdentName = isProd
  ? '[local]-[hash:base64:6]'
  : '[path][name]__[local]-[hash:base64:6]';
```

Sets the format of the class names generated by CSS Modules after compilation.

### Default value

`localIdentName` has different default values in development and production.

In a production, Rsbuild will generate shorter class names to reduce the bundle size.

```ts
import styles from './index.module.scss';

// In development, the value is `src-index-module__header-[hash]`
// In production, the value is `header-[hash]`
console.log(styles.header);
```

### Placeholders

You can use the following placeholders in `localIdentName`:

- `[name]` - the basename of the asset.
- `[local]` - original class.
- `[hash]` - the hash of the string.
- `[folder]` - the folder relative path.
- `[path]` - the relative path.
- `[file]` - filename and path.
- `[ext]` - extension with leading dot.
- `[hash:<hashDigest>:<hashDigestLength>]`: hash with hash settings. `hashDigest` is the [hash encodings](https://rspack.rs/config/output#outputhashdigest), and `hashDigestLength` is the length of the hash value.

### Example

Set `localIdentName` to other value, for example, the shorter 5-character hash value:

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      localIdentName: '[hash:base64:5]',
    },
  },
};
```

:::tip
If the hash length is set too short, it may increase the risk of class name conflicts.
:::

## cssModules.mode

- **Type:**

```ts
type Mode =
  | 'local'
  | 'global'
  | 'pure'
  | 'icss'
  | ((resourcePath: string) => 'local' | 'global' | 'pure' | 'icss');
```

- **Default:** `'local'`

Controls the mode of compilation applied to the CSS Modules.

### Optional values

`cssModules.mode` can take one of the following values:

1. `'local'` (default): This enables the CSS Modules specification for scoping CSS locally. Class and ID selectors are rewritten to be module-scoped, and `@value` bindings are injected.
2. `'global'`: This opts-out of the CSS Modules behavior, disabling both local scoping and injecting `@value` bindings. Global selectors are preserved as-is.
3. `'pure'`: This enables dead-code elimination by removing any unused local classnames and values from the final CSS. It still performs local scoping and `@value` injection.
4. `'icss'`: This compiles to the low-level Interoperable CSS format, which provides a syntax for declaring `:import` and `:export` dependencies between CSS and other languages. It does not perform any scoping or `@value` injection.

The `'local'` mode is the most common use case for CSS Modules, enabling modular and locally-scoped styles within components. The other modes may be used in specific scenarios.

For example:

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      mode: 'global',
    },
  },
};
```

### Function

You can also pass a function to `cssModules.mode` that determines the mode based on the resource path, query, or fragment. This allows you to use different modes for different files.

For example, to use local scoping for `.module.css` files and global styles for other files:

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      mode: (resourcePath) => {
        if (/\.module\.css$/.test(resourcePath)) {
          return 'local';
        }
        return 'global';
      },
    },
  },
};
```

## cssModules.namedExport

- **Type:** `boolean`
- **Default:** `false`

Whether to enable ES modules named export for class names.

```ts title="rsbuild.config.ts"
export default {
  output: {
    cssModules: {
      namedExport: true,
    },
  },
};
```

### Example

```css title="style.module.css"
.foo {
  color: blue;
}
```

- `namedExport: false`:

```js
import styles from './style.module.css';

console.log(styles.foo);
```

- `namedExport: true`:

```js
import { foo } from './style.module.css';
// or
import * as styles from './style.module.css';

console.log(foo);
console.log(styles.foo);
```

:::tip
When `namedExport` is set to true, the `default` class exported by CSS Modules will be automatically renamed to `_default` class because `default` is a reserved word in ECMA modules.
:::
