Navela
Navela

Reputation: 1983

using css modules how do I define more than one style name

I am trying to use multiple classes for an element using css modules. How do I do this?

function Footer( props) {
    const { route } = props;
    return (
        <div className={styles.footer}>
            <div className={styles.description, styles.yellow}>
              <p>this site was created by me</p>
            </div>
            <div className={styles.description}>
              <p>copyright nz</p>
            </div>
        </div>
    );
}

Upvotes: 182

Views: 192252

Answers (15)

Si Thu
Si Thu

Reputation: 1380

Thanks to Royer Adames, I would like to suggest this solution

const joinClasses = (...classes: string[]) => {
    return classes.map((className) => styles[className]).join(" ");
};

<article className={joinClasses("student", "student-expand-view-layout")}>

Upvotes: 1

Dev Ayush
Dev Ayush

Reputation: 133

you can use string concatenation with space(' ') ->

import classes from '../path/to/fileName.module.css'
<div className={classes.centerFlexY + ' ' + classes.searchTabs} />

className is nothing but a prop which we are passing, and this prop require a string value so we can use every single code which results in string inside {} block of className:

<div className={`${classes.imported} normalCssClass ${classes.another}`}

Upvotes: 5

j j
j j

Reputation: 11

You can add multiple classes using css modules as follows:

className={styles.description + ' ' + styles.yellow}

Upvotes: 1

Royer Adames
Royer Adames

Reputation: 1076

This can get out of hand quickly:

 className={`${styles.description} ${styles.yellow}`}

I like creating a function that sets the class and call that:

const setClass = (classes: string[]) => {
    return classes.map((className) => styles[className]).join(" ");
  };
<article className={setClass(["student", "student-expand-view-layout"])}>

Upvotes: 4

Olcay
Olcay

Reputation: 348

You should add square brackets to make the classNames an array, and to remove ',' add join().

function Footer( props) {
    const { route } = props;
    return (
        <div className={styles.footer}>
            <div className={ [styles.description, styles.yellow].join(' ') }>
              <p>this site was created by me</p>
            </div>
            <div className={styles.description}>
              <p>copyright nz</p>
            </div>
        </div>
    );
}

Upvotes: 13

Alex Alan Nunes
Alex Alan Nunes

Reputation: 194

The best solution for my case is the function bellow. 'Cause with the aruments destructuring I can return the classes with spaces.

export function clx(...classes) {
  return classes.join(" ");
}
// className={clx('border', styles.form, styles.h1, 'classe-4')}
// class="border form_CDE h1_AB"

Upvotes: 2

Abraham
Abraham

Reputation: 15640

Simply do

<div className={style.smallFont + " " + style.yellowColor}>

string concatination

Upvotes: 0

Yamo93
Yamo93

Reputation: 512

If you're using the classnames package and you want to apply a style conditionally, you need to use a dynamic property key with brackets, like this:

<div className={classNames(styles.formControl, { [styles.hidden]: hidden })}>
</div>

Upvotes: 3

Yassine Ejjoud
Yassine Ejjoud

Reputation: 1

Install classnames package to join classNames together

npm install classnames --save

Solution:

import cx from 'classnames';

Function footer(props) {
 ...
 <div className={cx(styles.description, styles.yellow)}>
}

Upvotes: 0

Sipke Schoorstra
Sipke Schoorstra

Reputation: 3409

As an addition to Yuan-Hao Chiang's answer, the following function makes it even easier to work with:

const classes = (classNames: Array<string> | string): string => classnames((Array.isArray(classNames) ? classNames : classNames.split(' ')).map(x => styles[x]));

What this does is take either an array or a string (which is then split into an array of strings), and returns a final class name (scoped to the current module since it uses the imported styles object of course).

You use it like this:

<div className={classes(['description', 'dark-theme', 'many', 'more', 'class-names'])}>

Or if you prefer, specify a single string (handy in case of using many classes when e.g. using TailwindCSS):

<div className={classes('description dark-theme many more class-names')}>

Upvotes: 2

Yuan-Hao Chiang
Yuan-Hao Chiang

Reputation: 2603

I highly recommend using the classnames package. It's incredibly lightweight (600 bytes minified) and has no dependencies:

import classnames from 'classnames';

Function footer(props) {
  ...
  <div className={classnames(styles.description, styles.yellow)}>
}

It even has the added benefit of being able to conditionally add class names (for example, to append a dark theme class), without having to concatenate strings which can accidentally add an undefined or false class:

  <div className={classnames(styles.description, {styles.darkTheme: props.darkTheme })}>

Upvotes: 34

f.jafari
f.jafari

Reputation: 568

for combine class names in front of className property, you can use "clsx", using this package is easy

import clsx from 'clsx';
// Strings
clsx('foo', 'bar', 'baz'); // 'foo bar baz'

// Objects
clsx({ foo:true, bar:false, baz:true });// 'foo baz'

you can find the package from this address: https://github.com/lukeed/clsx

Upvotes: 0

Dudeonyx
Dudeonyx

Reputation: 1099

You can use an array that will be joined with a space. i.e

<div className={[styles.App, styles.bold, styles['d-flex-c']].join(' ')}>

I prefer this to using template literals like @steven iseki suggested because it is easier to add and remove classes without having to wrap them in ${} every single time.

But if you're for some reason adding a lot of classes to a lot of elements you can write a higher order function to make it easier

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

console.log(styles);
// sample console output =>
// {
//   App: 'App_App__3TjUG',
//   'd-flex-c': 'App_d-flex-c__xpDp1',
// }


// func below returns a function that takes a list of classes as an argument
// and turns it in an array with the spread operator and reduces it into a spaced string

const classLister = styleObject => (...classList) =>
  classList.reduce((list, myClass) => {
    let output = list;
    if (styleObject[myClass]) {
      if (list) output += ' '; // appends a space if list is not empty
      output += styleObject[myClass]; 
      //Above: append 'myClass' from styleObject to the list if it is defined
    }
    return output;
 }, '');

const classes = classLister(styles); 
// this creates a function called classes that takes class names as an argument
// and returns a spaced string of matching classes found in 'styles'

Usage

<div className={classes('App', 'bold', 'd-flex-c')}>

Looks very neat and readable.

When rendered to the DOM it becomes

<div class="App_App__3TjUG App_d-flex-c__xpDp1">
/* Note: the class 'bold' is automatically left out because
   in this example it is not defined in styles.module.css 
   as you can be observe in console.log(styles) */

As expected

And it can be used with conditionals by putting the conditionally generated classes in an array that is used as an argument for classes via ... spread operator

In fact while answering this I decided to publish an npm module because why not.

Get it with

npm install css-module-class-lister

Upvotes: 55

svnm
svnm

Reputation: 24308

You can add multiple classes using css modules as follows:

className={`${styles.description} ${styles.yellow}`}

e.g.

function Footer( props) {
    return (
        <div className={styles.footer}>
            <div className={`${styles.description} ${styles.yellow}`}>
              <p>this site was created by me</p>
            </div>
        </div>
    );
}

Using react-css-modules you can use normal class name syntax:

<div styleName='description yellow'>

and you specify allowMultiple: true for multiple classes

Upvotes: 358

Riesenfaultier
Riesenfaultier

Reputation: 7

Why you don't define an additional class with the multiple styles? like

div .descyellow{
  background_color: yellow;
  style...
}

and then

<div class="descyellow">

Upvotes: -2

Related Questions