574

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"));
simhumileco
  • 27,137
  • 16
  • 123
  • 105
Hector
  • 5,815
  • 3
  • 12
  • 14
  • I found a breif answer here https://stackoverflow.com/a/36209517/4125588, just use JavaScript to join this classes, static or dynamic, with '+' operator, remember to insert ' ' before the classes except the first one, as the real class in HTML should be like 'a b c', also space between them. – Fadeoc Khaos Aug 08 '17 at 01:31
  • Possible duplicate of [Passing in class names to react components](https://stackoverflow.com/questions/32230635/passing-in-class-names-to-react-components) – dashdashzako Nov 15 '18 at 10:05
  • 2
    Why don't `classNames={{foo: true, bar: true, baz: false}}` and `classNames={["foo", "bar"]}` just _work_? – Peter V. Mørch Mar 02 '20 at 09:57
  • Then why are you assigning only one class name "active" to the li element? – John McGovern Jun 30 '20 at 20:34
  • You can check out https://www.npmjs.com/package/@ivanhanak_com/react-join-classnames, where basically you can use `
    `
    – Ivan Hanák Jul 07 '20 at 19:47

37 Answers37

566

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'}`} />
Damian Pavlica
  • 26,228
  • 8
  • 66
  • 73
  • This results in ``. Do note the extra space in beginning. This is valid, but ugly. Even react FAQ recommends another way or using the classnames package: https://reactjs.org/docs/faq-styling.html – Nakedible Oct 20 '18 at 16:22
  • 7
    I can't comprehend why you'd import a library (as in the accepted answer) to just set some classes that can be set using Vanilla JavaScript, which is a more efficient, cleaner, and readable solution, anyways. – Marcus Parsons May 17 '19 at 19:03
  • 4
    This is the correct answer. Using a dependency for this as suggested in the "correct" answer is overkill. – Chunky Chunk Oct 04 '19 at 17:50
  • 2
    I always love this answer but don't like that extra space in the end in case of falsy values. You can easily avoid then with `trim()`. – giovannipds Oct 22 '20 at 22:49
  • And if you're worried about having too many classes and a long template string, well, go on and break it in many lines, then use `replace`: `\`button ${true ? "style-2" : ""} ${false ? "disabled" : ""} \`.trim().replace('\n', ' ')` – giovannipds Oct 22 '20 at 22:59
  • 3
    @CodyMoniz and this answer guided me in the right direction! I had a situation where I needed to add multiple "variable" classes. `className={ \`${ props.variable } ${ props.variabletwo }\` }` worked! hours of not knowing how to search for this, remedied by this answer. – Matt Mintun Jan 08 '21 at 22:33
292

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.

Jack
  • 19,841
  • 11
  • 47
  • 47
  • do you have to import it? – e18r Apr 13 '16 at 21:54
  • 351
    That's too bad you had to bring in a library of classnames just to add two classes to an element :( – user959690 Apr 10 '18 at 22:37
  • 22
    @user959690 This is an example. This library is very nice when you're doing these things a lot and you have complex logic on when classes need to be applied or not. If you're doing something simple then sure just use templates, but every case is different and the reader should pick the right tool for their job. – Jack Apr 11 '18 at 17:06
  • 19
    @user959690 It's worth noting that it is now [installed by NPM when using Webpack](https://github.com/JedWatson/classnames/issues/111), so `import classNames from 'classnames'` then to use in a component `className={classNames(classes.myFirstClass, classes.mySecondClass)} `. – Hooligancat Jun 08 '18 at 19:39
  • 6
    No need to use an external library, see my answer below. – Huw Davies Aug 09 '18 at 03:17
  • 2
    Library has other advantages : `var btnClass = classNames({ btn: true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered }); return ;` – AmitJS94 Nov 05 '19 at 08:29
  • Consider using `['class1', null].filter(c => c).join(' ')` instead of a external package just for this. Sometimes doesn't worth it. – giovannipds Oct 22 '20 at 22:31
  • Or even better, template literals with `trim` to avoid that last space (if you're a dumb boring person, like me): `\`class1 ${yourvar ? 'class2' : ''}\`.trim()`. Short and sweet. – giovannipds Oct 22 '20 at 22:45
  • And if you're worried about having too many classes and a long template string, well, go on and break it in many lines, then use `replace`: `\`button ${true ? "style-2" : ""} ${false ? "disabled" : ""} \`.trim().replace('\n', ' ')` – giovannipds Oct 22 '20 at 22:57
  • Comment by @user959690 worked perfectly for me, thanks fellas – Nosnibor Mar 20 '21 at 17:47
245

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'} />
0xcaff
  • 12,036
  • 4
  • 41
  • 55
167

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}`
Jamie Hutber
  • 24,715
  • 40
  • 159
  • 259
  • 2
    This worked for me, along with '-' names, ie: – Flinkman Sep 09 '16 at 13:38
  • 1
    LOL, i crack my head and the answer is simple concat :D. Btw this alsow work with CSS Loader Module – GusDeCooL May 08 '17 at 07:54
  • The problem with that is that you can't have optional classes (if undefined, then it will not be added), so it depends wither you are sure your class is not null (not optional). In case of optional there isn't better then a helper like classes(). we can use a ternary with templates like that `className={`slider${className? ` ${className}`: ''}`}``. But it's a lot. [note: 'something '+undefined = 'something underfined'. Js dynamic conversion. – Mohamed Allal Nov 02 '18 at 15:59
  • 2
    Sure you can, just declare a variable above and use it conditionally :) – Jamie Hutber Mar 03 '19 at 00:06
  • Forgot everything is actually just JavaScript and never tried this. Thanks, was a great help. – Wylie Aug 26 '21 at 09:34
93

This can be achieved with ES6 template literals:

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

(edited for clarity)

Cody Moniz
  • 4,317
  • 2
  • 21
  • 20
46

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>
nightlyop
  • 7,095
  • 5
  • 26
  • 35
  • 1
    Did you test this? I did :) – raven May 29 '16 at 08:29
  • 1
    Yes I did. Actually, I'm using it quite often but just saw and corrected a typo. Of course the string containing the class names in the first line has to be made using `"` instead of `'`. Sorry about that. – nightlyop May 30 '16 at 08:37
26

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 ;)

Hristo Eftimov
  • 11,041
  • 12
  • 49
  • 74
20

Vanilla JS

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

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>
Huw Davies
  • 721
  • 10
  • 19
  • 1
    Vanilla JS is NOT ES6. But I do like your example. – RyanNerd Aug 21 '18 at 19:16
  • 10
    @RyanNerd Do you mean "ES6 is not vanilla JS"? Anyway, it is, because vanilla js means javascript without any frameworks. ES6 is a newer version of javascript. - https://stackoverflow.com/a/20435685/5111113 – Huw Davies Aug 22 '18 at 03:49
  • Not a wrong answer but could be improved a lot. For example, everyone else added examples about states. – JGallardo Oct 15 '19 at 21:25
  • This looks quite clean, and better for this simple case for sure. But worth mentioning that when there are multiple classes that depends on states, template strings can become quite hard to write and worst to read. In those cases, using `classnames` library would make life easier. But again, for a simple example like that, template strings is the way to go for sure! – Augusto Peres Feb 16 '22 at 16:15
20

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.

17

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>
ashuvssut
  • 909
  • 5
  • 15
10

Maybe classnames can help you.

var classNames = require('classnames');
classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test'
xsong
  • 460
  • 1
  • 4
  • 15
9

You could do the following:

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

A short and simple solution, hope this helps.

Alberto Perez
  • 2,267
  • 1
  • 12
  • 20
8

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)}>
Yanga
  • 2,655
  • 1
  • 27
  • 30
7

Just adding, we can filter out empty strings.

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

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>
arvinda kumar
  • 611
  • 7
  • 5
7

for more classes adding

... className={`${classes.hello} ${classes.hello1}`...
ROOT
  • 10,813
  • 5
  • 29
  • 43
Rama Krishna
  • 71
  • 1
  • 1
5

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

Achintha Isuru
  • 1,876
  • 15
  • 19
5

This seem to work for me

<Link className={[classes.button, classes.buttonFirst]}>
atazmin
  • 3,144
  • 1
  • 22
  • 12
4

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 ''
}
scazzy
  • 871
  • 2
  • 7
  • 19
4

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>
4

Create a function like this

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

Call it when needed.

<div className={cssClass("head",Style.element,"black")}><div>
himansa eshan
  • 164
  • 3
  • 10
4

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

jasonleonhard
  • 8,968
  • 71
  • 54
3

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}>
Michael Murphy
  • 1,702
  • 2
  • 15
  • 19
2

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} />
    )
  }
Vlad Bezden
  • 72,691
  • 22
  • 233
  • 168
2

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} />
    )
}
Seth
  • 618
  • 6
  • 7
  • Why use closures if you can do the same with map or reduce? ```function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }``` – Евгений Савичев May 26 '20 at 19:33
2

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]}
Jitesh Prajapati
  • 2,661
  • 4
  • 28
  • 47
2

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>
Caleb Hensley
  • 193
  • 1
  • 6
2

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>
Saurav gupta
  • 187
  • 1
  • 5
1

That's what I do:

Component:

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

Calling Component:

<Button className = 'hashButton free anotherClass' />
RegarBoy
  • 2,808
  • 17
  • 41
1

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>
Devakhim
  • 111
  • 1
  • 4
  • This is what I was doing (albeit no MUI) and doesn't work, only applies the first class - no warning or complain. – Juan Lanus Nov 23 '19 at 18:12
1

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...

StefaDesign
  • 826
  • 8
  • 17
  • 1
    I prefer your solution among all, with the following alterations: no space is needed after any type of classnames (static, dynamic, props): "component " vs "component", dynamic classnames work with simple brackets also which is 3 character less than string literals: `${conditionalClassname}` vs (conditionalClassname), and would extend your example with props received classnames which I prefer to use with string literals: ` ${propClassname}` - note the space between ` and $. – Rich Sep 13 '21 at 10:15
  • Thank you for suggestion @Rich. I agree we could save some characters that is for sure. I left it this way to be more obvious from the reason of understanding this example/use case, so not to get people confused with blank spaces, but I love your suggestion -makes perfect sense. Thank you! – StefaDesign Sep 13 '21 at 17:40
0

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"
morajabi
  • 147
  • 5
  • 15
0

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
Anupam
  • 7,870
  • 3
  • 42
  • 62
0

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
Ridwan Ajibola
  • 571
  • 7
  • 12
0

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"
pheianox
  • 279
  • 1
  • 11
0

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)

Vladimir Pankov
  • 111
  • 1
  • 6
-1

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>