Style Loader

[![npm][npm]][npm-url] [![node][node]][node-url] [![deps][deps]][deps-url] [![tests][tests]][tests-url] [![coverage][cover]][cover-url] [![chat][chat]][chat-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 ``` 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"], }, ], }, }; ``` ## Options | Name | Type | Default | Description | | :-------------------------------------------: | :------------------: | :---------: | :--------------------------------------------------------- | | [**`injectType`**](#injecttype) | `{String}` | `styleTag` | Allows to setup how styles will be injected into the DOM | | [**`attributes`**](#attributes) | `{Object}` | `{}` | Adds custom attributes to tag | | [**`insert`**](#insert) | `{String\|Function}` | `head` | Inserts tag at the given position into the DOM | | [**`styleTagTransform`**](#styleTagTransform) | `{String\|Function}` | `undefined` | Transform tag and css when insert 'style' tag into the DOM | | [**`base`**](#base) | `{Number}` | `true` | Sets module ID base (DLLPlugin) | | [**`esModule`**](#esmodule) | `{Boolean}` | `true` | Use ES modules syntax | ### `injectType` Type: `String` Default: `styleTag` Allows to setup how styles will be injected into the DOM. Possible values: - `styleTag` - `singletonStyleTag` - `autoStyleTag` - `lazyStyleTag` - `lazySingletonStyleTag` - `lazyAutoStyleTag` - `linkTag` #### `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 ``. > ⚠ 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: `Object` Default: `{}` If defined, the `style-loader` will attach given attributes with their values on ` ``` ### `insert` Type: `String|Function` Default: `head` By default, the `style-loader` appends `` and works faster. > ⚠ 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 > ⚠ Names of locals are converted to `camelCase`. > ⚠ It is not allowed to use JavaScript reserved words in css class names. > ⚠ 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 There are two ways to work with `nonce`: - using the `attributes` option - using the `__webpack_nonce__` variable > ⚠ 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 [deps]: https://david-dm.org/webpack-contrib/style-loader.svg [deps-url]: https://david-dm.org/webpack-contrib/style-loader [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 [chat]: https://badges.gitter.im/webpack/webpack.svg [chat-url]: https://gitter.im/webpack/webpack [size]: https://packagephobia.now.sh/badge?p=style-loader [size-url]: https://packagephobia.now.sh/result?p=style-loader