CSS Modules: How do they work in Vue?

Managing your styles throughout an application as a developer can be highly demanding If you write your CSS styles from scratch. With CSS Modules, you have more precise control over your element styles. Additionally, you can create different versions of your styles while using a modular method to design your application.

This article examines CSS Modules, their advantages, and how we can integrate them into a Vue.js application. It also includes code examples and a description of each part to clarify the concepts.

If you’re interested, you can clone the full project from GitHub.

Prerequisites

To understand how CSS Modules function, you need to have a basic understanding of the Vue project setup and previous experience working with CSS styles. 

This article will cover the following topics:

  1. What is CSS Module?
  2. Why are CSS Modules important?
  3. Integrating CSS Modules in a Vue.js application
  4. CSS Modules vs. styled components
  5. Conclusion

What is CSS Module?

A CSS Module is a file that, by default, scopes all of your class names and animations locally. It enables you to build styles in a CSS file and import them into a JavaScript object with the properties from the CSS definitions. The compose feature can be used to expand and modularize style declarations.

Why are CSS Modules important?

CSS modules are important because they provide a more pleasant way for developers to create maintainable styles in the time of components, manage element styles precisely, and build distinct layers of styles with a single module. 

Before we get started, let’s check out some common basic example of how CSS Modules work in JavaScript before implementing it in Vue:

Note: For the following example to work, you will need a webpack or Parcel library to import your CSS file into the bundle so it can be consumed as a module. For more information, you can check out a working example here.

The CSS file contains all the styles for our card. CSS Modules enable you to build styles in a CSS file and import them into a JavaScript object with the properties from the definitions:

Card.css file

@import url("https://fonts.googleapis.com/css2?family=Work+Sans&display=swap");

body {
  font-family: "Work Sans", sans-serif;
}

.card {
  box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.4);
  width: 30%;
  margin: auto;
}

.img {
  width: 100%;
}

.container {
  padding: 30px 16px;
  line-height: 2rem;
}
.heading {
  font-size: 2rem;
  font-weight: 1rem;
}

.link {
  background-color: black;
  color: white;
  padding: 10px 20px;
  text-decoration: none;
}

Now, we can import the styles into our JavaScript file via a template literal, in this case:

index.js file

import cardStyle from "./card.css";

document.getElementById("app").innerHTML = `
<div class="${cardStyle.card}">
<img src="https://img.freepik.com/free-photo/tractor-agricultural-machine-cultivating-field_342744-896.jpg?w=996&t=st=1660627603~exp=1660628203~hmac=fd1cb771af3a1c50fab957c0b88646fbe15d27cd0dfe5753f96cab390f4e7857" alt="Trulli" class="${cardStyle.img}">

  <div class="${cardStyle.container}">
    <h1 class="${cardStyle.heading}">Our Products</h1> 
    <p> To provide the best-tasting produce, we take extra care to choose and develop certain crop kinds where the excellent flavor is the focus.</p> 
    <a 
    class="${cardStyle.link}" href="https://parceljs.org" target="_blank" rel="noopener noreferrer">Learn More</a>
  </div>
</div>

`;

The following screenshot is the resulting output:

basic implementation of CSS module in JavaScript

As you can see, the styles from our classes are applied as desired.

Integrating CSS Module in a Vue.js application

The above code example covered the basic implementation of CSS Modules in JavaScript by importing the styles into our file using the curly bracket and $ sign, e.g., ${stylename}".

We can also achieve this in a Vue application, so let’s see how we can integrate it in the same way.

To use CSS Modules in Vue, add the “module” attribute to the style block and reference classes as seen in the JavaScript example below:

<template>
  <section>
    <div>
      <h1 :class="$style.heading">User Profile</h1>
    </div>
    
  </section>
</template>


<style module>
.heading {
  font-size: 50px;
  font-weight: 900;
  text-align: center;
}
</style>

How does it work in Vue?

Let’s build a simple user profile that displays a picture, name, and position of a user code example.
To do this, the first step is to create a file UserProfile in our component folder. Next, we add the “module” attribute to our <style> element, then use the $style syntax to access the class names in our dynamic class binding :class

<template>
  <section>
    <div>
      <h1 :class="$style.heading">Employee Profile</h1>
    </div>
    <div :class="$style.display">
      <div :class="$style.card">
        <img src="../assets/avatar-1.png" alt="Avatar" :class="$style.img" />
        <div :class="$style.container">
          <h3 :class="$style.name">Jesse Michael</h3>
          <p>Project Manager</p>
          <p>[email protected]</p>
          <span :class="$style.action">
            <a href="mailto:" :class="$style.message">&#9993; Message</a>
            <a href="mailto:" :class="$style.call">&#9743; Call</a>
            <a href="mailto:" :class="$style.follow">+ Follow</a>
          </span>
        </div>
      </div>

      <div :class="$style.card">
        <img src="../assets/avatar-2.png" alt="Avatar" :class="$style.img" />
        <div :class="$style.container">
          <h3 :class="$style.name">John Michael</h3>
          <p>Head of Marketing</p>
          <p>[email protected]</p>
          <span :class="$style.action">
            <a href="mailto:" :class="$style.message">&#9993; Message</a>
            <a href="mailto:" :class="$style.call">&#9743; Call</a>
            <a href="mailto:" :class="$style.follow">+ Follow</a>
          </span>
        </div>
      </div>
      <div :class="$style.card">
        <img src="../assets/avatar-3.png" alt="Avatar" :class="$style.img" />
        <div :class="$style.container">
          <h3 :class="$style.name">Gabriel Luke</h3>
          <p>CTO</p>
          <p>[email protected]</p>
          <span :class="$style.action">
            <a href="mailto:" :class="$style.message">&#9993; Message</a>
            <a href="mailto:" :class="$style.call">&#9743; Call</a>
            <a href="mailto:" :class="$style.follow">+ Follow</a>
          </span>
        </div>
      </div>
    </div>
  </section>
</template>

Next, we will add the “module” attribute inside the style tag, in the UserProfile:

<style module>
.display {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 0.6rem;
  place-items: center;
}
.card {
  box-shadow: 0 5px 9px 0 rgba(0, 0, 0, 0.4);
  width: 80%;
}

.container {
  padding: 10px 16px;
}

.heading {
  font-size: 50px;
  font-weight: 900;
  text-align: center;
}

.img {
  width: 20%;
  border-radius: 10px;
  margin-left: 7px;
  margin-top: 7px;
}
.action {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.message {
  background-color: #2563eb;
  color: #2563eb;
  padding: 9px;
  text-decoration: none;
  margin: 5px 0px;
  background: rgba(59, 130, 246, 0.1);
  border-radius: 16px;
}
.call {
  background-color: #ca8a04;
  color: #ca8a04;
  padding: 9px;
  text-decoration: none;
  margin: 5px 0px;
  border-radius: 16px;
  background: rgba(234, 179, 8, 0.1);
}
.follow {
  background-color: #16a34a;
  color: #16a34a;
  padding: 10px;
  text-decoration: none;
  margin: 5px 0px;
  background: rgba(34, 197, 94, 0.1);
  border-radius: 16px;
}
</style>

The preceding code should produce the output in the screenshot below:

CSS module in Vue.js

When we check our application, the build tool converts our class names into variables. For example, the class name for the first card is UserProfile_container_1X6ae when we inspect it:

A look at the variables behind Vue module

CSS Modules vs. styled components

CSS Modules and styled components are both suitable for your application, but one is more relevant than the other one. Most developers love implementing styled components because it’s easier and helps developers reuse the same styles in a different application. In CSS Modules, you must create your CSS in a file and inject it into your JavaScript, whereas for styled components, you just write your styles inside your components and use them wherever the components are used.

You can create reusable styles with both CSS Modules and styled components. If you’re interested in implementing any of the styles, you need to be aware of several different things, including: 

  • Performance
  • Learning curve
  • Integration

Conclusion

When your application grows, managing styles can get complicated. One issue you’ll encounter is namespace collision. However, CSS Modules help you avoid this issue by assigning new variable names to your class names.

Additionally, by designing your application utilizing a modular strategy, it’s much easier to maintain control over your styles and create a variety of style layers. 

This article discussed CSS modules and how to use them. Hopefully, it will help you integrate CSS Modules into your Vue application. Good luck!

If you like articles like this, browse the Mattermost library and continue your learning.
This blog post was created as part of the Mattermost Community Writing Program and is published under the CC BY-NC-SA 4.0 license. To learn more about the Mattermost Community Writing Program, check this out.

Read more about:

CSS Vue.js

Ezekiel Lawson is currently a technical writer and software developer, aside from building web tools and applications, He enjoys educating people and simplifying complicated issues for their easy understanding by sharing resources that will guide developers.