CSS Modules

requires ^9.8.0

CSS Modules is a popular system for modularizing and composing CSS. vue-loader provides first-class integration with CSS Modules as an alternative for simulated scoped CSS.


Just add the module attribute to your <style>:

<style module>
.red {
  color: red;
.bold {
  font-weight: bold;

This will turn on CSS Modules mode for css-loader, and the resulting class identifier object will be injected into the component as a computed property with the name $style. You can use it in your templates with a dynamic class binding:

  <p :class="$style.red">
    This should be red

Since it's a computed property, it also works with the object/array syntax of :class:

    <p :class="{ [$style.red]: isRed }">
      Am I red?
    <p :class="[$style.red, $style.bold]">
      Red and bold

And you can also access it from JavaScript:

export default {
  created () {
    // -> "_1VyoJ-uZOjlOxP7jWUy19_0"
    // an identifier generated based on filename and className.

Refer to the CSS Modules spec for mode details such as global exceptions and composition.

Custom Inject Name

You can have more than one <style> tags in a single *.vue component. To avoid injected styles to overwrite each other, you can customize the name of the injected computed property by giving the module attribute a value:

<style module="a">
  /* identifiers injected as a */

<style module="b">
  /* identifiers injected as b */

Configuring css-loader Query

CSS Modules are processed via css-loader. With <style module>, the default query used for css-loader is:

  modules: true,
  importLoaders: 1,
  localIdentName: '[hash:base64]'

You can use vue-loader's cssModules option to provide additional query options to css-loader:

module: {
  rules: [
      test: '\.vue$',
      loader: 'vue-loader',
      options: {
        cssModules: {
          localIdentName: '[path][name]---[local]---[hash:base64:5]',
          camelCase: true

results matching ""

    No results matching ""