Skip to content

Using Multiple Classes With React CSS Modules

React/

When working with CSS modules in React, applying styles from one class is straightforward. But, what about using multiple or nested class selectors?

In this post, I will show you how to use multiple classes on one element using CSS modules in React. I will also teach you what to do when you have nested class selectors.

If you are using Sass/SCSS modules, I have it covered at the end of the post as well.

Working with Many Classes in CSS Modules

Let’s start by applying styling from a single class in CSS modules.

Create a CSS module file — Button.module.css.

.button {
  background-color: #ffffff;
  border: 1px solid #2779e4;
  border-radius: 7px;
  color: #000000;
  font-size: 1rem;
  padding: 0.75rem 1.25rem;
}

These are some basic styles to create an outlined button.

Import the Button.module.css file in your React component and apply the button styling.

import React from 'react';
import styles from './Button.module.css';

export default function Button() {
  return (
    <button className={styles.button} type="button">
      Click me
    </button>
  );
}

Thanks to how CSS modules work, the styles.button will apply a unique value to className attribute of the button element. Because of that, the styles for .button selector coming from Button.module.css won’t clash with other styles in the project if they also use a .button selector.

Now let’s apply multiple classes from a CSS module to a single element.

In this case, let’s create a modifier for the outlined button to make it filled instead.

.button.filled {
  background-color: #2779e4;
  color: #ffffff;
}

First of, to apply multiple classes to className in React, you can use template literals.

<div className={`${firstClass} ${secondClass} thirdClass fourthClass`}></div>

If you want to use a value from a variable, you can wrap it around ${}. Otherwise, write it as a string.

It might seem like you can throw the modifier class right in there, but it won’t work.

{/* ❌ Won't load styles for the 'filled' class in Button.module.css */}
<button type="button" className={`${styles.button} filled`}>
  Click here
</button>

The filled class won’t match the .filled styles defined in Button.module.css. That’s because the filled class coming from CSS modules looks more something like this _filled_gjkwa_3 when rendered in your application.

CSS modules work by creating a unique identifier for each class individually, even if the selector chains together multiple classes or nests them.

So, to apply multiple CSS modules classes, you have to set the className to use both classes individually.

{/* ✅ Will load 'filled' class styles */}
<button type="button" className={`${styles.button} ${styles.filled}`}>
  Click here
</button>

You can apply this idea further to apply as many classes as you want.

Button.module.css
.button {}
.button.filled {}
.button.filled.active {}
Button.js
{/* 1️⃣ .button */}
<button className={`${styles.button}`}>1</button>

{/* 2️⃣ .button.filled */}
<button className={`${styles.button} ${styles.filled}`}>2</button>

{/* 3️⃣ .button.filled.active */}
<button className={`${styles.button} ${styles.filled} ${styles.active}`}>3</button>

Using Nested Classes in CSS Modules

If you have a CSS selector that applies styles to an element only when it is a child of an element with a specific class like so:

Card.module.css
.card {
  background-color: #ffffff;
  border: 1px solid #cccccc;
  border-radius: 10px;
  box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px,
    rgba(60, 64, 67, 0.15) 0px 2px 6px 2px;
}

.card .body {
  padding: 1rem 1.25rem;
}

.card .header {
  border-bottom: 1px solid #cccccc;
  padding: 1rem 1.25rem;
}

In this case — .header and .body need to have a parent with a .card class.

You have to specify the child class on the child element and the parent class on the parent for the styles to work.

Card.js
import React from 'react';
import styles from './Card.module.scss';

export default function Card() {
  return (
    <div className={styles.card}>
      <div className={styles.header}>
        <h2>Card Title</h2>
      </div>
      <div className={styles.body}>Card Content</div>
    </div>
  );
}

The child styles are applied from styles.header property, although it might seem like they should be nested under styles.card.header instead.

Multiple and Nested Classes in SCSS

Rewriting the previous CSS examples in SCSS looks something like this:

.button {
  background-color: #ffffff;
  // ✂️

  &.filled {
    background-color: #a84118;
  }
}

This code will apply styles to an element with a .button class and an element with both .button and .filled classes.

Using SCSS instead of CSS in CSS modules won’t change the way you apply multiple classes.

import React from 'react';
import styles from './Button.module.scss';

export default function Card() {
  return (
    <>
      {/* .button */}
      <button className={`${styles.button}`}>One</button>

      {/* .button.filled */}
      <button className={`${styles.button} ${styles.filled}`}>Two</button>
    </>
    );
}

And, the same works for nested classes as well.

.card {
  // ✂️

  .header {
    // ✂️
  }

  .body {
    // ✂️
  }
}
import React from 'react';
import styles from './Card.module.scss';

export default function Card() {
  return (
    <div className={styles.card}>
      <div className={styles.header}>
        <h2>Card Title</h2>
      </div>
      <div className={styles.body}>Card Content</div>
    </div>
  );
}

Although you are nesting the selectors, the properties remain directly under styles.