How to add multiple classes to a ReactJS Component?

JavascriptCssReactjsEcmascript 6

Javascript Problem Overview


I am new to ReactJS and JSX and I am having a little problem with the code below.

I am trying to add multiple classes to the className attribute on each li:

<li key={index} className={activeClass, data.class, "main-class"}></li>

My React component is:

var AccountMainMenu = React.createClass({
  getInitialState: function() {
    return { focused: 0 };
  },

  clicked: function(index) {
    this.setState({ focused: index });
  },

  render: function() {
    var self = this;
    var accountMenuData = [
      {
        name: "My Account",
        icon: "icon-account"
      },
      {
        name: "Messages",
        icon: "icon-message"
      },
      {
        name: "Settings",
        icon: "icon-settings"
      }
    /*{
        name:"Help &amp; Support &nbsp; <span class='font-awesome icon-support'></span>(888) 664.6261",
        listClass:"no-mobile last help-support last"
      }*/
    ];

    return (
      <div className="acc-header-wrapper clearfix">
        <ul className="acc-btns-container">
          {accountMenuData.map(function(data, index) {
            var activeClass = "";

            if (self.state.focused == index) {
              activeClass = "active";
            }

            return (
              <li
                key={index}
                className={activeClass}
                onClick={self.clicked.bind(self, index)}
              >
                <a href="#" className={data.icon}>
                  {data.name}
                </a>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
});

ReactDOM.render(<AccountMainMenu />, document.getElementById("app-container"));

Javascript Solutions


Solution 1 - Javascript

I use ES6 template literals. For example:

const error = this.state.valid ? '' : 'error'
const classes = `form-control round-lg ${error}`

And then just render it:

<input className={classes} />

One-liner version:

<input className={`form-control round-lg ${this.state.valid ? '' : 'error'}`} />

Solution 2 - Javascript

I use classnames when there is a fair amount of logic required for deciding the classes to (not) use. An overly simple example:

...
    var liClasses = classNames({
      'main-class': true,
      'activeClass': self.state.focused === index
    });
    
    return (<li className={liClasses}>{data.name}</li>);
...

That said, if you don't want to include a dependency then there are better answers below.

Solution 3 - Javascript

Just use JavaScript.

<li className={[activeClass, data.klass, "main-class"].join(' ')} />

If you want to add classes based keys and values in an object you can use the following:

function classNames(classes) {
  return Object.entries(classes)
    .filter(([key, value]) => value)
    .map(([key, value]) => key)
    .join(' ');
}

const classes = {
  'maybeClass': true,
  'otherClass': true,
  'probablyNotClass': false,
};

const myClassNames = classNames(classes);
// Output: "maybeClass otherClass"

<li className={myClassNames} />

Or even simpler:

const isEnabled = true;
const isChecked = false;

<li className={[isEnabled && 'enabled', isChecked && 'checked']
  .filter(e => !!e)
  .join(' ')
} />
// Output:
// <li className={'enabled'} />

Solution 4 - Javascript

Concat

No need to be fancy I am using CSS modules and it's easy

import style from '/css/style.css';

<div className={style.style1+ ' ' + style.style2} />

This will result in:

<div class="src-client-css-pages-style1-selectionItem src-client-css-pages-style2">

In other words, both styles

Conditionals

It would be easy to use the same idea with if's

const class1 = doIHaveSomething ? style.style1 : 'backupClass';

<div className={class1 + ' ' + style.style2} />

ES6

For the last year or so I have been using the template literals, so I feel its worth mentioning, i find it very expressive and easy to read:

`${class1} anotherClass ${class1}`

Solution 5 - Javascript

This can be achieved with ES6 template literals:

<input className={`base-input-class ${class1} ${class2}`}>

(edited for clarity)

Solution 6 - Javascript

You can create an element with multiple class names like this:

<li className="class1 class2 class3">foo</li>

Naturally, you can use a string containing the class names and manipulate this string to update the class names of the element.

var myClassNammes = 'class1 class2 class3';
...
<li className={myClassNames}>foo</li>

Solution 7 - Javascript

This is how you can do that with ES6:

className = {`
      text-right
      ${itemId === activeItemId ? 'active' : ''}
      ${anotherProperty === true ? 'class1' : 'class2'}
`}

You can list multiple classes and conditions and also you can include static classes. It is not necessary to add an additional library.

Good luck ;)

Solution 8 - Javascript

Vanilla JS

No need for external libraries - just use ES6 template strings:

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>

Solution 9 - Javascript

I don't think we need to use an external package for just adding multiple classes.

I personally use

<li className={`li active`}>Stacy</li>

or

<li className={`li ${this.state.isActive ? 'active' : ''}`}>Stacy<li>

or

<li className={'li ' + (this.state.isActive ? 'active' : '') }>Stacy<li>

the second and third one in case you need to add or remove classes conditionally.

Solution 10 - Javascript


Generally people do like

<div className={  `head ${style.class1} ${Style.class2}`  }><div>

OR

<div className={  'head ' + style.class1 + ' ' + Style.class2 }><div>

OR

<div className={  ['head', style.class1 , Style.class2].join(' ')  }><div>

But you can choose to Create a function to do this job

function joinAll(...classes) {
  return classes.join(" ")
}

then call it like:-

<div className={joinAll('head', style.class1 , style.class2)}><div>

Solution 11 - Javascript

Maybe classnames can help you.

var classNames = require('classnames');
classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test'

Solution 12 - Javascript

You could do the following:

<li key={index} className={`${activeClass} ${data.class} main-class`}></li>

A short and simple solution, hope this helps.

Solution 13 - Javascript

It can be done with https://www.npmjs.com/package/clsx :

https://www.npmjs.com/package/clsx

First install it:

npm install --save clsx

Then import it in your component file:

import clsx from  'clsx';

Then use the imported function in your component:

<div className={ clsx(classes.class1, classes.class2)}>

Solution 14 - Javascript

Just adding, we can filter out empty strings.

className={[
	'read-more-box',
	this.props.className,
	this.state.isExpanded ? 'open' : 'close',
].filter(x => !!x).join(' ')}

Solution 15 - Javascript

You can create an element with multiple class names like this, I tryed these both way, its working fine...

If you importing any css then you can follow this way : Way 1:

import React, { Component, PropTypes } from 'react';
import csjs from 'csjs';
import styles from './styles';
import insertCss from 'insert-css';
import classNames from 'classnames';
insertCss(csjs.getCss(styles));
export default class Foo extends Component {
  render() {
    return (
      <div className={[styles.class1, styles.class2].join(' ')}>
        { 'text' }
      </div>
    );
  }
}

way 2:

import React, { Component, PropTypes } from 'react';
import csjs from 'csjs';
import styles from './styles';
import insertCss from 'insert-css';
import classNames from 'classnames';
insertCss(csjs.getCss(styles));
export default class Foo extends Component {
  render() {
    return (
      <div className={styles.class1 + ' ' + styles.class2}>
        { 'text' }
      </div>
    );
  }
}

**

If you applying css as internal :

const myStyle = {
  color: "#fff"
};

// React Element using Jsx
const myReactElement = (
  <h1 style={myStyle} className="myClassName myClassName1">
    Hello World!
  </h1>
);

ReactDOM.render(myReactElement, document.getElementById("app"));

.myClassName {
  background-color: #333;
  padding: 10px;
}
.myClassName1{
  border: 2px solid #000;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
<div id="app">
  
</div>

Solution 16 - Javascript

for more classes adding

... className={`${classes.hello} ${classes.hello1}`...

Solution 17 - Javascript

I know this is a late answer, but I hope this will help someone.

Consider that you have defined following classes in a css file 'primary', 'font-i', 'font-xl'

  • The first step would be to import the CSS file.
  • Then

<h3 class = {` ${'primary'} ${'font-i'} font-xl`}> HELLO WORLD </h3>

would do the trick!

For more info: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20

Solution 18 - Javascript

This seem to work for me

<Link className={[classes.button, classes.buttonFirst]}>

Solution 19 - Javascript

Late to the party, but why use third party for such a simple problem?

You could either do it as @Huw Davies mentioned - the best way

1. <i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>
2. <i className={[styles['foo-bar-baz'], 'fa fa-user', 'fa-2x'].join(' ')}

Both are good. But writing can become complex for a large app. To make it optimal, I do the same above things but put it in a helper class

Using my below helper function, allows me to keep the logic separate for future editing, and also gives me multiple ways to add the classes

classNames(styles['foo-bar-baz], 'fa fa-user', 'fa-2x')

or

classNames([styles['foo-bar-baz], 'fa fa-user', 'fa-2x'])

This is my helper function below. I've put it in a helper.js where I keep all my common methods. Being such a simple function, I avoided using 3rd party to keep control

export function classNames (classes) {
    if(classes && classes.constructor === Array) {
        return classes.join(' ')
    } else if(arguments[0] !== undefined) {
        return [...arguments].join(' ')
    }
    return ''
}

Solution 20 - Javascript

You can use arrays and then join them using space.

<li key={index} className={[activeClass, data.class, "main-class"].join(' ')}></li>

This will result in :

<li key={index} class="activeClass data.class main-class"></li>

Solution 21 - Javascript


Create a function like this

function cssClass(...c) {
  return c.join(" ")
}

Call it when needed.

<div className={cssClass("head",Style.element,"black")}><div>

Solution 22 - Javascript

When I have many varying classes, I have found the following to be useful.

The filter removes any of the null values and the join puts all the remaining values into a space separated string.

const buttonClasses = [
    "Button", 
    disabled ? "disabled" : null,
    active ? "active" : null
].filter((class) => class).join(" ")

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>

Solution 23 - Javascript

Using CSS Modules (or Sass Modules) you can isolate your styling to a specific component too.

"Component-scoped CSS allows you to write traditional, portable CSS with minimal side effects: gone are the worries of selector name collisions or affecting other components’ styles."

import * as styles from "./whatever.module.css"  // css version
import * as styles from "./whatever.module.scss" // sass version

<div className={`${styles.class1} ${styles.class2}`}>
   INSERT YOUR CODE HERE
</div>

Ref1 Ref2

Solution 24 - Javascript

Using facebook's TodoTextInput.js example

render() {
    return (
      <input className={
        classnames({
          edit: this.props.editing,
          'new-todo': this.props.newTodo
        })}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  } 

replacing classnames with plain vanilla js code will look like this:

render() {
    return (
      <input
        className={`
          ${this.props.editing ? 'edit' : ''} ${this.props.newTodo ? 'new-todo' : ''}
        `}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  }

Solution 25 - Javascript

If you don't feel like importing another module, this function works like the classNames module.

function classNames(rules) {
    var classes = ''

    Object.keys(rules).forEach(item => {    
        if (rules[item])
            classes += (classes.length ? ' ' : '') + item
    })

    return classes
} 

You can use it like this:

render() {
    var classes = classNames({
        'storeInfoDiv': true,  
        'hover': this.state.isHovered == this.props.store.store_id
    })   

    return (
        <SomeComponent style={classes} />
    )
}

Solution 26 - Javascript

Use https://www.npmjs.com/package/classnames

import classNames from 'classnames';

  1. Can use multiple classes using comas seperated:

     <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
    
  2. Can use multiple classes using comas separated with condition:

     <li className={classNames(classes.buttonArea, !nodes.length && classes.buttonAreaHidden)}>Hello World</li> 
    

Using array as props to classNames will also work, but gives warning e.g.

className={[classes.tableCellLabel, classes.tableCell]}

Solution 27 - Javascript

clsx makes this simple!

> "The clsx function can take any number of arguments, each of which can > be an Object, Array, Boolean, or String." > > -- clsx docs on npmjs.com

Import it:

import clsx from 'clsx'

Use it:

<li key={index} className={clsx(activeClass, data.class, "main-class")}></li>

Solution 28 - Javascript

I used this syntax

    <div
      className={[
        "d-inline-flex justify-content-center align-items-center ",
        withWrapper && `ft-icon-wrapper ft-icon-wrapper-${size}`,
        wrapperClass,
      ].join(" ")}
    >
      <img
        className={`ft-icon ft-icon-${size} ${iconClass}`}
        alt={id}
        src={icon}
      />
    </div>

Solution 29 - Javascript

That's what I do:

Component:

const Button = ({ className }) => (
  <div className={ className }> </div>
);

Calling Component:

<Button className = 'hashButton free anotherClass' />

Solution 30 - Javascript

I am using React 16.6.3 and @Material UI 3.5.1, and is able to use arrays in className like className={[classes.tableCell, classes.capitalize]}

So in your example, the following would be similar.

<li key={index} className={[activeClass, data.class, "main-class"]}></li>

Solution 31 - Javascript

I usually use it like this : (in your case)

    <li  key={index} className={
        "component " +
        `${activeClass? activeClass: " not-an-active-class "}` +
        `${data.class? " " + data.class : " no-data-class "}`
   } />

When it comes to JSX and (usually) we have some json... than you loop it ... component.map, plus some conditional to check if json property exists to render class name depending on property value from JSON. In example below component_color and component_dark_shade are properties from component.map()

   <div className={
        "component " +
        `${component_color? component_color: " no-color "}` +
        `${component_dark_shade? " " + component_dark_shade : " light "}`
   }/>

Output : <div class="component no-color light" .... Or: <div class="component blue dark" .... depending on values from map...

Solution 32 - Javascript

I use rc-classnames package.

// ES6
import c from 'rc-classnames';

// CommonJS
var c = require('rc-classnames');

<button className={c('button', {
  'button--disabled': isDisabled,
  'button--no-radius': !hasRadius
})} />

You can add classes in any format (Array, Object, Argument). All truthy values from arrays or Arguments plus keys in objects that equal to true get merged together.

for example:

ReactClassNames('a', 'b', 'c') // => "a b c"
ReactClassNames({ 'a': true, 'b': false, c: 'true' }) // => "a c"
ReactClassNames(undefined, null, 'a', 0, 'b') // => "a b"

Solution 33 - Javascript

I bind classNames to the css module imported to into the component.

import classNames from 'classnames'; 
import * as styles from './[STYLES PATH];
const cx = classNames.bind(styles); 

classnames gives the ability to declare className for a React element in a declarative way.

ex:

<div classNames={cx(styles.titleText)}> Lorem </div>

<div classNames={cx('float-left')}> Lorem </div> // global css declared without css modules
<div classNames={cx( (test === 0) ?
             styles.titleText : 
             styles.subTitleText)}>  Lorem </div> // conditionally assign classes

<div classNames={cx(styles.titleText, 'float-left')}> Lorem </div> //combine multiple classes

Solution 34 - Javascript

If you wanna use a double conditional css module is always somehow confusing so i would advise you to follow this pattern

import styles from "./styles.module.css"

const Conditonal=({large, redColor}) => {
 return(
  <div className={[large && styles.large] + [redColor && styles.color]>
   ...
  </div>
 )
}

export default Conditonal

and if its just one conditonal statement with two class name, use this

import styles from "./styles.module.css"

const Conditonal=({redColor}) => {
 return(
  <div className={styles.large + [redColor && styles.color]>
   ...
  </div>
 )
}

export default Conditonal

Solution 35 - Javascript

Use jbcn module. (BEM support)

https://www.npmjs.com/package/jbcn

Example:

const classNames = jbcn({ 
    btn: { 
        alpha: true, 
        beta: true, 
        gamma: false 
    } 
});

// ==> "btn btn--alpha btn--beta"
const classNames = jbcn({
    expand: true,
    hide: false,

    btn: { 
        alpha: true, 
        beta: true, 
        gamma: false 
    } 
});

// ==> "expand btn btn--alpha btn--beta"

Solution 36 - Javascript

Bad idea to join CSS classes using a string concatenation. There are multiple cases where it is very confusing and overwhelming. Better to add some simple helper which join all of these into the one string. Here is example:

import isString from 'lodash/isString';
import isObject from 'lodash/isObject';
/**
 * Helper function for conditionally creating css class strings.
 *
 * Example usage:
 *   classNames('foo', ['bar', ''], { baz: false, bob: true });
 *   => 'foo bar bob'
 *
 * @module helpers/classNames
 * @param {...(String|String[]|Object)} args
 * @returns {String}
 */
export default function classNames(...args) {
  const classes = [];
  for (const arg of args) {
    if (arg !== null && typeof arg !== 'undefined') {
        if (isString(arg)) {
          classes.push(arg);
        } else if (Array.isArray(arg)) {
          classes.push(classNames(...arg));
        } else if (isObject(arg)) {
          classes.push(classNames(...Object.keys(arg).filter(k => arg[k])));
        }
    }
  }
  return classes.join(' ');
}

(from https://tomsoir.medium.com/react-css-classnames-concatenation-pattern-fd0fa1f31143)

Solution 37 - Javascript

Just use a comma!

const useStyles = makeStyles((theme) => ({
 rightAlign: {
  display: 'flex',
  justifyContent: 'flex-end',
 },
 customSpacing: {
  marginTop: theme.spacing(2.5),
 },
)};

<div className={(classes.rightAlign, classes.customSpacing)}>Some code</div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHectorView Question on Stackoverflow
Solution 1 - JavascriptDamian PavlicaView Answer on Stackoverflow
Solution 2 - JavascriptJackView Answer on Stackoverflow
Solution 3 - Javascript0xcaffView Answer on Stackoverflow
Solution 4 - JavascriptJamie HutberView Answer on Stackoverflow
Solution 5 - JavascriptCody MonizView Answer on Stackoverflow
Solution 6 - JavascriptnightlyopView Answer on Stackoverflow
Solution 7 - JavascriptHristo EftimovView Answer on Stackoverflow
Solution 8 - JavascriptHuw DaviesView Answer on Stackoverflow
Solution 9 - JavascriptPasham Akhil Kumar ReddyView Answer on Stackoverflow
Solution 10 - JavascriptashuvssutView Answer on Stackoverflow
Solution 11 - JavascriptxsongView Answer on Stackoverflow
Solution 12 - JavascriptAlberto PerezView Answer on Stackoverflow
Solution 13 - JavascriptYangaView Answer on Stackoverflow
Solution 14 - JavascriptHimanshu JariyalView Answer on Stackoverflow
Solution 15 - Javascriptarvinda kumarView Answer on Stackoverflow
Solution 16 - JavascriptRama KrishnaView Answer on Stackoverflow
Solution 17 - JavascriptAchintha IsuruView Answer on Stackoverflow
Solution 18 - JavascriptatazminView Answer on Stackoverflow
Solution 19 - JavascriptscazzyView Answer on Stackoverflow
Solution 20 - JavascriptVinay JariyaView Answer on Stackoverflow
Solution 21 - Javascripthimansa eshanView Answer on Stackoverflow
Solution 22 - JavascriptMichael MurphyView Answer on Stackoverflow
Solution 23 - JavascriptjasonleonhardView Answer on Stackoverflow
Solution 24 - JavascriptVlad BezdenView Answer on Stackoverflow
Solution 25 - JavascriptSethView Answer on Stackoverflow
Solution 26 - JavascriptVikramjit SinghView Answer on Stackoverflow
Solution 27 - JavascriptCaleb HensleyView Answer on Stackoverflow
Solution 28 - JavascriptSaurav guptaView Answer on Stackoverflow
Solution 29 - JavascriptRegarBoyView Answer on Stackoverflow
Solution 30 - JavascriptDevakhimView Answer on Stackoverflow
Solution 31 - JavascriptStefaDesignView Answer on Stackoverflow
Solution 32 - JavascriptmorajabiView Answer on Stackoverflow
Solution 33 - JavascriptRajendra kumar VankadariView Answer on Stackoverflow
Solution 34 - JavascriptRidwan AjibolaView Answer on Stackoverflow
Solution 35 - JavascriptpheianoxView Answer on Stackoverflow
Solution 36 - JavascriptVladimir PankovView Answer on Stackoverflow
Solution 37 - JavascriptAnkush MundhraView Answer on Stackoverflow