rollup-plugin-react-scoped-css
raw JSON → 1.2.3 verified Mon Apr 27 auth: no javascript
A Rollup and Vite plugin that provides component-level CSS scoping for React, similar to Vue and Angular's scoped styles. Current stable version is 1.2.3 (released March 2026), updated regularly with dependency bumps. It adds a unique data attribute to JSX elements and rewrites CSS selectors to match, enabling style isolation without CSS Modules. Unlike CSS Modules, it works with preprocessors (SCSS, Less) and does not require renaming class names. Requires Node >= 18 and Vite >= 5. Ships TypeScript types.
Common errors
error Error [ERR_REQUIRE_ESM]: require() of ES Module /node_modules/rollup-plugin-react-scoped-css/dist/index.js from not supported. ↓
cause Trying to require() an ESM-only module with CJS require().
fix
Use import syntax or dynamic import(). If using CommonJS config file, rename to .mjs or use import() inside async function.
error Error: Cannot find module 'vite' ↓
cause Missing peer dependency 'vite' when using plugin in Rollup without Vite.
fix
Install vite as devDependency: npm install -D vite. Or use in a Vite project.
error Error: Target element is not a JSX element. (line X, col Y) ↓
cause Attempting to scope a non-JSX file (e.g., .js) that contains JSX but file extension not recognized.
fix
Add the file extension to jsxFileExtensions option: reactScopedCssPlugin({ jsxFileExtensions: ['jsx', 'tsx', 'js'] })
error Error: 'reactScopedCssPlugin' is not a function ↓
cause Incorrect import: using default import when package exports named export.
fix
Use import { reactScopedCssPlugin } from '...' (named import) or check your bundler configuration.
Warnings
breaking v1.0.0 changed to ESM-only; CJS require() will fail. ↓
fix Migrate to ESM imports (import { reactScopedCssPlugin } from 'rollup-plugin-react-scoped-css') or use dynamic import().
breaking v1.0.0 dropped support for Node < 18 and Vite < 5. ↓
fix Upgrade Node to >= 18 and Vite to >= 5.
deprecated The `include` and `exclude` options have been deprecated since v1.2.0 in favor of Vite's built-in filter. ↓
fix Remove `include`/`exclude` from plugin options; use Vite's `plugins` array filtering if needed.
gotcha Scoped styles apply per file, not per component. Multiple components in the same file share the same scope. ↓
fix Keep one component per file or manually ensure unique class names.
gotcha The plugin does not transpile CSS preprocessors (SCSS, Less) when used without Vite. You need to add separate plugins for those. ↓
fix For Rollup without Vite, add @rollup/plugin-scss or similar before reactScopedCssPlugin.
gotcha When using Rollup alone, the plugin returns an array of two plugins. You must insert them in the correct position relative to other CSS plugins. ↓
fix Use: const [pre, post] = reactScopedCssPlugin(); plugins: [pre, /* other CSS plugins */, post]
Install
npm install rollup-plugin-react-scoped-css yarn add rollup-plugin-react-scoped-css pnpm add rollup-plugin-react-scoped-css Imports
- reactScopedCssPlugin wrong
const reactScopedCssPlugin = require('rollup-plugin-react-scoped-css')correctimport { reactScopedCssPlugin } from 'rollup-plugin-react-scoped-css' - reactScopedCssPlugin (default)
import reactScopedCssPlugin from 'rollup-plugin-react-scoped-css' - FilterPattern types wrong
import { FilterPattern } from 'rollup-plugin-react-scoped-css'correctimport type { FilterPattern } from 'rollup-plugin-react-scoped-css'
Quickstart
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { reactScopedCssPlugin } from 'rollup-plugin-react-scoped-css'
export default defineConfig({
plugins: [react(), reactScopedCssPlugin()]
})
// Component.jsx
import './Component.scoped.css'
export default function Component() {
return (
<div className="wrap">
<h1>Hello</h1>
</div>
)
}
/* Component.scoped.css */
.wrap h1 { color: red; }