> ## Documentation Index
> Fetch the complete documentation index at: https://extension.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# CSS Modules in browser extensions

> Scope styles and avoid naming collisions across browser extension popups, options UIs, and content scripts with zero-config CSS Modules via the Rspack pipeline.

Extension.js supports CSS Modules with zero configuration for module-style filenames (for example, `styles.module.css`). It routes them through the Rspack CSS pipeline. Class names stay locally scoped to the component that imported them.

## When CSS Modules are a good fit

* You need local class scoping without adopting a full CSS-in-JS stack.
* You share components across popup/options/new-tab surfaces.
* You want predictable style ownership in larger extension codebases.

## Template examples

### `content-css-modules`

<img src="https://mintcdn.com/extensionjs/VCnDd7fX2Nza24SE/images/examples/content-css-modules/screenshot.png?fit=max&auto=format&n=VCnDd7fX2Nza24SE&q=85&s=fc9a0ef0f5626975cef352ceaee86080" alt="content-css-modules template screenshot" width="2400" height="1800" data-path="images/examples/content-css-modules/screenshot.png" />

Add locally scoped styles to content-script UI with minimal setup.

<CodeGroup>
  ```bash npm theme={null}
  npx extension@latest create my-extension --template=content-css-modules
  ```

  ```bash pnpm theme={null}
  pnpx extension@latest create my-extension --template=content-css-modules
  ```

  ```bash yarn 2+ theme={null}
  yarn dlx extension@latest create my-extension --template=content-css-modules
  ```

  ```bash bun theme={null}
  bunx extension@latest create my-extension --template=content-css-modules
  ```

  ```bash deno theme={null}
  deno run -A npm:extension@latest create my-extension --template=content-css-modules
  ```
</CodeGroup>

Repository: [extension-js/examples/content-css-modules](https://github.com/extension-js/examples/tree/main/examples/content-css-modules)

## Usage with an existing extension

To use CSS Modules, name files with a module suffix:

* `*.module.css`
* `*.module.scss`
* `*.module.sass`
* `*.module.less`

Use the related language pages for Sass and Less setup requirements.

```diff theme={null}
- myComponentCss.css
+ myComponentCss.module.css
```

### Usage example

After renaming your stylesheet, import and use it in your component:

```ts theme={null}
import styles from "./styles/myComponent.module.css";

const button = document.createElement("button");
button.className = styles.primary;
button.innerText = "Click here";
document.body.appendChild(button);
```

## How it works

Extension.js enables Rspack CSS support and handles module imports through the CSS module pipeline:

* Default import style maps (`import styles from "./x.module.css"`)
* Rspack generates scoped class names through its CSS module pipeline
* Module class exports work directly in JS/TS/TSX files

In extension page contexts (for example, popup/options/new tab), module imports produce unique, scoped class names as expected.

## Content script note

Content scripts get the same treatment as extension pages. Rspack generates scoped class
names, exports them to your JavaScript, and Extension.js registers the emitted stylesheet in
the manifest `content_scripts[].css` entry, and in `web_accessible_resources` so it can also
be injected into a shadow root. Import the class names you need and apply them:

```ts theme={null}
import {primary} from "./styles/myComponent.module.css";

const button = document.createElement("button");
button.className = primary;
```

See the `content-css-modules` template above for a working example.

## React/Preact example usage

For React or Preact, you can import and use the CSS module in the component like this:

```jsx theme={null}
import styles from "./styles/myComponent.module.css";

export default function NewTabPage() {
  return <button className={styles.primary}>Click here</button>;
}
```

## Vue example usage

In Vue, you can use module classes from single-file component (SFC) styles:

```vue theme={null}
<template>
  <button :class="$style.primary">Click here</button>
</template>

<style module>
@import "./styles/myComponent.module.css";
</style>
```

## Svelte example usage

In Svelte, import module mappings and apply class names:

```svelte theme={null}
<script>
  import styles from "./styles/myComponent.module.css";
</script>

<button class={styles.primary}>Click here</button>
```

## Best practices

* Keep module styles close to components (`Component.module.css`) for easier ownership.
* Use `:global(...)` sparingly and only for intentional global overrides.
* Prefer module styles for extension pages and framework components where class mapping is explicit.

## Next steps

* Learn more about [Sass and Sass modules](/docs/languages-and-frameworks/sass).
* Learn more about [Less and Less modules](/docs/languages-and-frameworks/less).

## Video walkthrough

<Frame>
  <iframe className="w-full aspect-video rounded-xl" src="https://www.youtube-nocookie.com/embed/ondh3B28ieQ?rel=0" title="Extension.js: Content CSS Modules template" loading="lazy" allow="encrypted-media; picture-in-picture; fullscreen" allowFullScreen />
</Frame>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.