Native CSS
This guide shows how to use webpack native CSS handling with experiments.css.
Getting Started
Enable native CSS support in your webpack configuration:
webpack.config.js
export default {
experiments: {
css: true,
},
};With this option enabled, webpack can process CSS without adding css-loader and mini-css-extract-plugin for the basic flow.
Importing CSS
After enabling the experiment, import .css files directly from JavaScript:
src/index.js
import "./styles.css";
const element = document.createElement("h1");
element.textContent = "Hello native CSS";
document.body.appendChild(element);src/styles.css
h1 {
color: #1f6feb;
}Webpack will process the CSS and include it in the build output.
CSS Modules
Native CSS support also includes CSS Modules. The recommended approach is:
- keep
type: "css/auto"for mixed CSS handling, - use
.module.css(or.modules.css) naming for CSS Modules files.
src/button.module.css
.button {
background: #0d6efd;
color: white;
border: 0;
border-radius: 4px;
padding: 8px 12px;
}src/index.js
import * as styles from "./button.module.css";
const button = document.createElement("button");
button.className = styles.button;
button.textContent = "Click me";
document.body.appendChild(button);You can customize CSS Modules behavior using parser and generator options:
webpack.config.js
export default {
experiments: {
css: true,
},
module: {
parser: {
"css/module": {
namedExports: true,
},
},
generator: {
"css/module": {
exportsConvention: "camel-case-only",
localIdentName: "[uniqueName]-[id]-[local]",
},
},
},
};Production Build
With experiments.css: true, webpack provides native CSS extraction and content hashing for CSS assets in production builds.
Compared to the classic setup:
- Traditional approach:
css-loader+mini-css-extract-plugin - Native approach:
experiments.csswith built-in extraction behavior
This reduces configuration and keeps the CSS pipeline closer to webpack core features.
Experimental Status & Known Limitations
experiments.css is explicitly experimental, so treat it as opt-in and test carefully before broad rollout.
Known points to keep in mind:
- APIs and behavior may still evolve before webpack v6 defaults.
- Some loader-specific options are not part of native CSS behavior (for example, loader-specific filters).
- If your project relies on advanced loader chains, validate each part before migrating fully.
Migration Guide
If you currently use css-loader, mini-css-extract-plugin, and style-loader, migrate in small steps.
1) Start from a classic setup
webpack.config.js
import MiniCssExtractPlugin from "mini-css-extract-plugin";
export default {
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [new MiniCssExtractPlugin()],
};2) Switch to native CSS
webpack.config.js
export default {
experiments: {
css: true,
},
};3) Migrate css-loader options first
Most CSS Modules-related options should move to native parser/generator config.
webpack.config.js
export default {
experiments: {
css: true,
},
module: {
parser: {
css: {
import: true,
url: true,
},
"css/module": {
namedExports: true,
},
},
generator: {
"css/module": {
exportsConvention: "camel-case-only",
localIdentName: "[uniqueName]-[id]-[local]",
},
},
},
};Notes:
importandurlare native parser switches for CSS handling.namedExportscontrols CSS Modules exports behavior.exportsConventionandlocalIdentNameprovide class export/name shaping.css-loaderfilter-style options are not available as direct equivalents; use webpack mechanisms such asIgnorePluginwhen needed.
4) Replace mini-css-extract-plugin
When experiments.css is enabled, webpack provides native CSS extraction and content hash handling for CSS output files.
That means you can remove:
MiniCssExtractPlugin.loaderfrommodule.rules,- the
new MiniCssExtractPlugin()plugin instance.
5) Replace style-loader with exportType: "style"
If you used style-loader for runtime style injection, keep css/auto and use module naming (.module.css or .modules.css), then set exportType: "style":
webpack.config.js
export default {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
parser: {
exportType: "style",
},
},
],
},
};This mode injects a <style> element from the webpack runtime and covers the typical style-loader use case.
If you cannot rename files to the CSS Modules naming convention, you can use type: "css/module" directly for the relevant rule.
6) Keep imports unchanged
Your JS imports can stay the same:
import "./styles.css";
import * as styles from "./button.module.css";7) Validate output in development and production
Check that:
- styles are applied correctly in development,
- generated CSS files are emitted for production,
- CSS Modules exports match your existing usage.



