CSS Modules in Vue.js
Tags: vue, css, cssmodules
Published: 2019-11-15 12:36:07

---
title: CSS Modules in Vue.js
published: true
description: Part three in a series of articles about working with CSS in Vue.js, focusing on using CSS Modules in Vue.js.
tags: vue, CSS, CSS Modules
cover_image: https://thepracticaldev.s3.amazonaws.com/i/xzleitrf3fzf455vn74u.png
canonical_url: https://redonion.se/en/css-modules-in-vue-js-2/
series: CSS with Vue.js
---
Part three in a series of articles about working with CSS in Vue.js, focusing on using CSS Modules in Vue.js.

In these types of javascript frameworks, it has become popular to use CSS Modules. It is a way of automatically creating unique class names, thereby preventing any possible style leaking or accidental cascading between elements.

Support for CSS Modules is already setup by default by the Vue CLI.

In the **.vue file** where you want to use CSS modules, add `module` to the style tag:
```html
<style module>
  .hello{
    background-color: mistyrose;
  }
</style>
```
In the **.vue file** template, the class name is then added though javascript:
```html
<div :class="$style.hello">
```

The `$style` prefix used in .vue file templates refers to any styles within the component (.vue file) style tag.

####Targeting Elements Without Defined Class Names
For targeting HTML elements without defined class names like `p` or `h1`, you would have to make sure they are related to their parent for them to be included in the module class name output.

In the example below, the `h3` style text-decoration underline will be added to the CSS as `.hello-[modulename-identifier] h3`. The `h3` outside of the `.hello` block will not be included in the `.hello-[modulename-identifier]` block and therefore risk affecting other `h3` tags outside of the module.
```html
<style module>
  .hello{
    background-color: mistyrose;
  }

  .hello h3{
    text-decoration: underline;
  }

  h3{
    margin: 1em 0;
  }
</style>
```
##Changing the Class Name
If you want to change the generated module class names, this can be done in the **vue.config.js** file:
```javascript
module.exports = {
  css: {
    loaderOptions: {
      css: {
        localIdentName: '[local][Frida][hash:base64:8]'
        // camelCase: 'only' //optional setting for how the name is output
      }
    }
  }
}
```
In the example above, I’ve added my name `Frida` followed by a random string to make sure the name is unique.

##Utilizing the Class Name
It is possible to use the expression `$style.hello` as a reference to the class name elsewhere within the vue component.
```html
<p>Printing $style.hello: {{ $style.hello }}</p>
```
The code above will output: “Printing $style.hello: hello-[modulename-identifier]”

This can also be used to for example target the element using JavaScript, access and print out its styles or do any other operation. Because of the module naming convention, the class name acts like an ID meaning there will be just one element with this specific name.

####Example: Outputting an Element Style
A very basic example where an element’s background-color is output.
In the **.vue file template section**:
```html
<p>Output: {{ $style.hello }} background-color is: {{ dataBackground }}</p>
<!-- Output: hello-[modulename-indentifier] background-color is: #ffe4e1 -->
```
In the **.vue file script section**:
```html
<script>
export default {
  data () {
    return {
      dataBackground: 'background'
    }
  },
  methods: {
    classNameBackground () {
      const elem = document.getElementsByClassName(this.$style.hello)[0]
      const compStyles = window.getComputedStyle(elem)
      const bg = compStyles.getPropertyValue('background-color')

      this.dataBackground = bg
      return bg
    }
  },
  mounted () {
    this.classNameBackground()
  }
}
</script>
```
In the **.vue file style section**:
```html
<style module>
  .hello{
    background-color: #ffe4e1;
  }
</style>
```
##CSS Modules :export
Another way of accessing information in the CSS style block is to use the `:export` feature in CSS Modules to export strings from the style tag:
```html
<template>
    <p>{{ $style.primaryColor }}</p>
    <!-- Outputs: #ffe4e1 -->
    <p>{{ $style.displayAs }}</p>
    <!-- Outputs: some-string -->
</template>

<style module lang=”scss”>
  $primary-color: #ffe4e1;

  :export {
    primaryColor: $primary-color;
    displayAs: some-string;
  }
</style>
```
Note that the `:export` feature seems restricted to working with strings. To get a specific CSS style from a named class, it might be better to go the JavaScript route as per the example above.

Read more about the `:export` feature in the [CSS Modules documentation](https://github.com/css-modules/icss), and more about CSS Modules in Vue, in the [vue-loader documentation](https://vue-loader.vuejs.org/guide/css-modules.html#usage).

##Importing Module Style Files
For when you want to place your CSS Module styles in separate files, rather than in the style tag in each .vue component file.

Create your style file and place it for example in the same folder as your component. Name it “filename.module.fileextension”. In my example, I’ve created the style file “HelloWorld.module.scss”. In **HelloWorld.module.scss**:
```css
.imported{
    background-color:green;
}
```
Import the style file in the script tag of the component where you want to use it, in this example **HelloWorld.vue**. I found that I also had to add the import to data:
```html
<script>
  import scssStyles from './HelloWorld.module.scss'
  export default {
    data () {
      return {
        scssStyles
      }
    }
  }
</script>
```
In the template part of your component, add the class by referencing the import name and the class name in the style file:
```html
<template>
  <p :class="scssStyles.imported">
</template>
```
####Make all CSS Files CSS Modules
If you want to be able to omit the extra “.module” in the file name, you can add this setting to the **vue.config.js file**:
```javascript
module.exports = {
  css: {
    modules: true
  }
}
```
However setting modules to true will at the same time also cause _all other style files_ to be working as CSS modules.

Note that the imported .module.scss file content is not available to the vue file component style tag, since the generated class names will differ. Also note that variables inside the imported file are not available to the component style tag. To achieve this, see the article [“Importing Style Files to Component Style Tags in Vue.js”](https://redonion.se/en/importing-style-files-to-component-style-tags-in-vue-js-2/).
***
####Setup
The starting code for this article is created by the Vue CLI command tool version 3.3.0 and Vue.js version 2.6.10. Note that both setup, plugins and framework are evolving. **Changes will in time most certainly happen that make the techniques described in this post less relevant.**

***