[![npm][npm]][npm-url]
[![node][node]][node-url]
[![tests][tests]][tests-url]
[![coverage][cover]][cover-url]
[![discussion][discussion]][discussion-url]
[![size][size]][size-url]
# style-loader
Inject CSS into the DOM.
## Getting Started
To begin, you'll need to install `style-loader`:
```console
npm install --save-dev style-loader
```
or
```console
yarn add -D style-loader
```
or
```console
pnpm add -D style-loader
```
It's recommended to combine `style-loader` with the [`css-loader`](https://github.com/webpack-contrib/css-loader)
Then add the loader to your `webpack` config. For example:
**style.css**
```css
body {
background: green;
}
```
**component.js**
```js
import "./style.css";
```
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
```
## Security Warning
This loader is primarily meant for development. The default settings are not safe for production environments. See the [recommended example configuration](#recommended) and the section on [nonces](#nonce) for details.
## Options
- [**`injectType`**](#injecttype)
- [**`attributes`**](#attributes)
- [**`insert`**](#insert)
- [**`styleTagTransform`**](#styleTagTransform)
- [**`base`**](#base)
- [**`esModule`**](#esmodule)
### `injectType`
Type:
```ts
type injectType =
| "styleTag"
| "singletonStyleTag"
| "autoStyleTag"
| "lazyStyleTag"
| "lazySingletonStyleTag"
| "lazyAutoStyleTag"
| "linkTag";
```
Default: `styleTag`
Allows to setup how styles will be injected into the DOM.
Possible values:
#### `styleTag`
Automatically injects styles into the DOM using multiple ``. It is **default** behaviour.
**component.js**
```js
import "./styles.css";
```
Example with Locals (CSS Modules):
**component-with-css-modules.js**
```js
import styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
```
All locals (class names) stored in imported object.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
// The `injectType` option can be avoided because it is default behaviour
{ loader: "style-loader", options: { injectType: "styleTag" } },
"css-loader",
],
},
],
},
};
```
The loader inject styles like:
```html
```
#### `singletonStyleTag`
Automatically injects styles into the DOM using one ``.
> **Warning**
>
> Source maps do not work.
**component.js**
```js
import "./styles.css";
```
**component-with-css-modules.js**
```js
import styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
```
All locals (class names) stored in imported object.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "singletonStyleTag" },
},
"css-loader",
],
},
],
},
};
```
The loader inject styles like:
```html
```
#### `autoStyleTag`
Works the same as a [`styleTag`](#styleTag), but if the code is executed in IE6-9, turns on the [`singletonStyleTag`](#singletonStyleTag) mode.
#### `lazyStyleTag`
Injects styles into the DOM using multiple `` on demand.
We recommend following `.lazy.css` naming convention for lazy styles and the `.css` for basic `style-loader` usage (similar to other file types, i.e. `.lazy.less` and `.less`).
When you `lazyStyleTag` value the `style-loader` injects the styles lazily making them useable on-demand via `style.use()` / `style.unuse()`.
> ⚠️ Behavior is undefined when `unuse` is called more often than `use`. Don't do that.
**component.js**
```js
import styles from "./styles.lazy.css";
styles.use();
// For removing styles you can use
// styles.unuse();
```
**component-with-css-modules.js**
```js
import styles from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = styles.locals["my-class"];
```
All locals (class names) stored in `locals` property of imported object.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.lazy\.css$/i,
use: [
{ loader: "style-loader", options: { injectType: "lazyStyleTag" } },
"css-loader",
],
},
],
},
};
```
The loader inject styles like:
```html
```
#### `lazySingletonStyleTag`
Injects styles into the DOM using one `` on demand.
We recommend following `.lazy.css` naming convention for lazy styles and the `.css` for basic `style-loader` usage (similar to other file types, i.e. `.lazy.less` and `.less`).
When you `lazySingletonStyleTag` value the `style-loader` injects the styles lazily making them useable on-demand via `style.use()` / `style.unuse()`.
> ⚠️ Source maps do not work.
> ⚠️ Behavior is undefined when `unuse` is called more often than `use`. Don't do that.
**component.js**
```js
import styles from "./styles.css";
styles.use();
// For removing styles you can use
// styles.unuse();
```
**component-with-css-modules.js**
```js
import styles from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = styles.locals["my-class"];
```
All locals (class names) stored in `locals` property of imported object.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.lazy\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "lazySingletonStyleTag" },
},
"css-loader",
],
},
],
},
};
```
The loader generate this:
```html
```
#### `lazyAutoStyleTag`
Works the same as a [`lazyStyleTag`](#lazyStyleTag), but if the code is executed in IE6-9, turns on the [`lazySingletonStyleTag`](#lazySingletonStyleTag) mode.
#### `linkTag`
Injects styles into the DOM using multiple `` .
> ℹ️ The loader will dynamically insert the `` tag at runtime via JavaScript. You should use [MiniCssExtractPlugin](https://webpack.js.org/plugins/mini-css-extract-plugin/) if you want to include a static ``.
```js
import "./styles.css";
import "./other-styles.css";
```
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.link\.css$/i,
use: [
{ loader: "style-loader", options: { injectType: "linkTag" } },
{ loader: "file-loader" },
],
},
],
},
};
```
The loader generate this:
```html
```
### `attributes`
Type:
```ts
type attributes = HTMLAttributes;
```
Default: `{}`
If defined, the `style-loader` will attach given attributes with their values on `
```
### `insert`
Type:
```ts
type insert =
| string
| ((htmlElement: HTMLElement, options: Record) => void);
```
Default: `head`
By default, the `style-loader` appends `` and works faster.
> **Warning**
>
> Do not use together `style-loader` and `mini-css-extract-plugin`.
**webpack.config.js**
```js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};
```
### Named export for CSS Modules
> **Warning**
>
> Names of locals are converted to `camelCase`.
> **Warning**
>
> It is not allowed to use JavaScript reserved words in css class names.
> **Warning**
>
> Options `esModule` and `modules.namedExport` in `css-loader` should be enabled.
**styles.css**
```css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
```
**index.js**
```js
import { fooBaz, bar } from "./styles.css";
console.log(fooBaz, bar);
```
You can enable a ES module named export using:
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: {
namedExport: true,
},
},
},
],
},
],
},
};
```
### Source maps
The loader automatically inject source maps when previous loader emit them.
Therefore, to generate source maps, set the `sourceMap` option to `true` for the previous loader.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
"style-loader",
{ loader: "css-loader", options: { sourceMap: true } },
],
},
],
},
};
```
### Nonce
If you are using a [Content Security Policy](https://www.w3.org/TR/CSP3/) (CSP), the injected code will usually be blocked. A workaround is to use a nonce. Note, however, that using a nonce significantly reduces the protection provided by the CSP. You can read more about the security impact in [the specification](https://www.w3.org/TR/CSP3/#security-considerations). The better solution is not to use this loader in production.
There are two ways to work with `nonce`:
- using the `attributes` option
- using the `__webpack_nonce__` variable
> **Warning**
>
> the `attributes` option takes precedence over the `__webpack_nonce__` variable
#### `attributes`
**component.js**
```js
import "./style.css";
```
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
attributes: {
nonce: "12345678",
},
},
},
"css-loader",
],
},
],
},
};
```
The loader generate:
```html
```
#### `__webpack_nonce__`
**create-nonce.js**
```js
__webpack_nonce__ = "12345678";
```
**component.js**
```js
import "./create-nonce.js";
import "./style.css";
```
Alternative example for `require`:
**component.js**
```js
__webpack_nonce__ = "12345678";
require("./style.css");
```
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
```
The loader generate:
```html
```
#### Insert styles at top
Inserts styles at top of `head` tag.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: function insertAtTop(element) {
var parent = document.querySelector("head");
var lastInsertedElement =
window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
window._lastElementInsertedByStyleLoader = element;
},
},
},
"css-loader",
],
},
],
},
};
```
#### Insert styles before target element
Inserts styles before `#id` element.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: function insertBeforeAt(element) {
const parent = document.querySelector("head");
const target = document.querySelector("#id");
const lastInsertedElement =
window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, target);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
window._lastElementInsertedByStyleLoader = element;
},
},
},
"css-loader",
],
},
],
},
};
```
#### Custom Elements (Shadow DOM)
You can define custom target for your styles for the `lazyStyleTag` type.
**webpack.config.js**
```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// Do not forget that this code will be used in the browser and
// not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
// we recommend use only ECMA 5 features,
// but it is depends what browsers you want to support
insert: function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
},
},
},
"css-loader",
],
},
],
},
};
```
Insert styles to the provided element or to the `head` tag if target isn't provided.
**custom-square.css**
```css
div {
width: 50px;
height: 50px;
background-color: red;
}
```
**custom-square.js**
```js
import customSquareStyles from "./custom-square.css";
class CustomSquare extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
const divElement = document.createElement("div");
divElement.textContent = "Text content.";
this.shadowRoot.appendChild(divElement);
customSquareStyles.use({ target: this.shadowRoot });
// You can override injected styles
const bgPurple = new CSSStyleSheet();
const width = this.getAttribute("w");
const height = this.getAttribute("h");
bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
this.shadowRoot.adoptedStyleSheets = [bgPurple];
// `divElement` will have `100px` width, `100px` height and `red` background color
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
```
## Contributing
Please take a moment to read our contributing guidelines if you haven't yet done so.
[CONTRIBUTING](./.github/CONTRIBUTING.md)
## License
[MIT](./LICENSE)
[npm]: https://img.shields.io/npm/v/style-loader.svg
[npm-url]: https://npmjs.com/package/style-loader
[node]: https://img.shields.io/node/v/style-loader.svg
[node-url]: https://nodejs.org
[tests]: https://github.com/webpack-contrib/style-loader/workflows/style-loader/badge.svg
[tests-url]: https://github.com/webpack-contrib/style-loader/actions
[cover]: https://codecov.io/gh/webpack-contrib/style-loader/branch/master/graph/badge.svg
[cover-url]: https://codecov.io/gh/webpack-contrib/style-loader
[discussion]: https://img.shields.io/github/discussions/webpack/webpack
[discussion-url]: https://github.com/webpack/webpack/discussions
[size]: https://packagephobia.now.sh/badge?p=style-loader
[size-url]: https://packagephobia.now.sh/result?p=style-loader