> ## 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.

# Less CSS in browser extensions

> Use Less CSS and Less modules across browser extension pages and UI components. Extension.js configures the Rspack preprocessor for .less files.

Use Less CSS across browser extension pages and UI components with a single pipeline that also supports module-scoped styles.

Extension.js detects Less usage, configures the preprocessors in the Rspack build, and supports both `.less` and `.module.less` files in browser extensions.

## When Less is a good fit

* You are migrating an existing Less-based web codebase.
* You want variables and nesting with low migration cost.
* You need module-scoped styles while keeping Less conventions.

## Template examples

### `new-less`

<img src="https://mintcdn.com/extensionjs/etcqPhDg4wwyPkcC/images/examples/newtab-less/screenshot.png?fit=max&auto=format&n=etcqPhDg4wwyPkcC&q=85&s=4dbd571767c198bb8191fbb7ac918a3b" alt="new-less template screenshot" width="2400" height="1800" data-path="images/examples/newtab-less/screenshot.png" />

Start a new-tab extension with Less support already configured.

<CodeGroup>
  ```bash npm theme={null}
  npx extension@latest create my-extension --template=newtab-less
  ```

  ```bash pnpm theme={null}
  pnpx extension@latest create my-extension --template=newtab-less
  ```

  ```bash yarn 2+ theme={null}
  yarn dlx extension@latest create my-extension --template=newtab-less
  ```

  ```bash bun theme={null}
  bunx extension@latest create my-extension --template=newtab-less
  ```

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

Repository: [extension-js/examples/newtab-less](https://github.com/extension-js/examples/tree/main/examples/newtab-less)

## Usage with an existing extension

Add Less to an existing extension with the steps below.

### Installation

Install the required dependencies:

<CodeGroup>
  ```bash npm theme={null}
  npm install -D less less-loader
  ```

  ```bash pnpm theme={null}
  pnpm add -D less less-loader
  ```

  ```bash yarn theme={null}
  yarn add -D less less-loader
  ```

  ```bash bun theme={null}
  bun add -d less less-loader
  ```

  ```bash deno theme={null}
  deno add -D npm:less npm:less-loader
  ```
</CodeGroup>

### Example usage in an HTML file

In extension pages (popup/options/new tab), import Less through your script entry:

```html theme={null}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>New Extension</title>
    <script src="./main.ts"></script>
  </head>
  <body>
    <h1 class="title">Hello, Extension.</h1>
  </body>
</html>
```

```ts theme={null}
import "./styles/globals.less";

console.log("Less loaded");
```

### In a `content_script` file

```ts theme={null}
import "./styles/content.less";

console.log("Content styles loaded");
```

## Less modules in browser extensions

Scope class names locally with Less modules, just like CSS Modules. This prevents global style conflicts by default, which matters in extensions because content scripts run inside a host page's CSS scope.

### `content-less-modules`

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

Use Less modules in content scripts when you need scoped styles on injected UI.

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

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

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

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

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

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

## Using Less modules in an existing extension

To enable Less modules, rename your `.less` files to include `.module.less`. This enables automatic local scoping of class names.

```diff theme={null}
- myStyles.less
+ myStyles.module.less
```

### Example usage

After renaming your Less file, you can import it into your scripts:

```ts theme={null}
import styles from "./styles/myStyles.module.less";

const element = document.createElement("h1");
element.className = styles.primary;
element.innerText = "Hello, Extension!";
document.body.appendChild(element);
```

## React/Preact example usage

To use Less modules in React or Preact, import your Less module and apply styles as you would in any component:

```jsx theme={null}
import styles from "./styles/myStyles.module.less";

export default function MyComponent() {
  return <h1 className={styles.primary}>Hello, Extension!</h1>;
}
```

## Vue example usage

In Vue, prefer single-file component (SFC) styles with `lang="less"` and `module`:

```vue theme={null}
<template>
  <h1 :class="$style.primary">Hello, Extension!</h1>
</template>

<style lang="less" module>
@import "./styles/myStyles.module.less";
</style>
```

## Svelte example usage

In Svelte, import Less module mappings and apply classes:

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

<h1 class={styles.primary}>Hello, Extension!</h1>
```

## Behavior notes

* In extension page contexts, `.module.less` exports class maps as expected.
* In content scripts, Extension.js emits styles as CSS assets and injects them as stylesheets into the page.
* If the `less` package is not installed, Extension.js warns and copies the raw Less source into the output CSS, so those surfaces render unstyled until you install it yourself.

## About the `less` post-install warning

With some package managers, installing a project that uses Less can surface a
notice that build scripts for `less` were not run (pnpm prints
`Ignored build scripts: less` and asks you to approve them). This is expected
and **safe to ignore**. Extension.js compiles Less through its own bundler
pipeline, so it does not rely on Less's optional post-install step (which only
sets up Playwright inside Less's own repository and is a no-op for consumers).
Your `.less` and `.module.less` files build and hot-reload the same either way.

Scaffolded projects do not ship a `pnpm.ignoredBuiltDependencies` key, so a
pnpm install of a Less template shows the notice like any other project. npm and
yarn run the script by default and print nothing.

If you hit the notice, you have two equivalent ways to silence it:

* **Skip it (recommended)**: add `pnpm.ignoredBuiltDependencies: ["less"]` to
  your `package.json`. This acknowledges the script without running the no-op.
* **Run it**: run `pnpm approve-builds` and select `less`, or add
  `pnpm.onlyBuiltDependencies: ["less"]`. Harmless, just unnecessary.

Either way there is no functional difference for typical Extension.js projects.

## Next steps

* Learn more about [CSS Modules](/docs/languages-and-frameworks/css-modules).
* Configure [PostCSS](/docs/integrations/postcss) in your extension.

## Video walkthrough

<Frame>
  <iframe className="w-full aspect-video rounded-xl" src="https://www.youtube-nocookie.com/embed/VGssDbxBeMM?rel=0" title="Extension.js: Content Less 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.