Mr. Benedict
Mr. Benedict

Reputation: 827

How to conditionally apply CSS classes in React JS

I've been musing on how best to conditionally apply a CSS class in React JS. I've seen some answers banding around but there aren't many out there or they're just not as elaborative as I'd like.

Upvotes: 33

Views: 91785

Answers (10)

saran3h
saran3h

Reputation: 14112

I find this tiny (~220 Bytes) package extremely helpful to avoid writing a lot of boilerplate code: https://www.npmjs.com/package/clsx

You could simply write:

import clsx from 'clsx';

<section className={clsx('zb-card', <some dynamic optional classNames>)}>
or
<section className={clsx('foo', true && 'bar', 'baz')}>
//=> 'foo bar baz'

Upvotes: 0

pgksunilkumar
pgksunilkumar

Reputation: 396

Single Condition with Static ClassName

<div className={"container " + (this.props.condition === true ? 'show' : 'hidden')}>

Double Condition with Static ClassName

<div className={"container " + (this.props.condition === true ? 'show ' : 'hidden ') + (this.props.secondCondition === true ? 'visible' : 'invisible')}>

need to give space between conditional class or static class by the end

Upvotes: 0

Audun Olsen
Audun Olsen

Reputation: 638

Many answers assume this is about conditionally toggling CSS classes (ternary if is adequate), but this become far more obtuse when you need to optionally include classnames. Multiple ternary ifs with empty false expressions is verbose. An NPM package may be a tad much. A function too may be overkill for some.

Here's what I do.

const classNames = [
  "className1",
  condition1 && "className2",
  condition2 && "className3",
  condition3 && "className4",
].filter(e => e).join(" ");

Edit as of June 2021

I'm noticing this answer still sees the occasional upvote. Thought I'd provide a slightly updated example using a small and succinct arrow function:

const cls = (...classes) => classes.filter(Boolean).join(' ');

<div className={cls('mandatoryClass', condition && 'optionalClass')} />

Upvotes: 13

Adam Orłowski
Adam Orłowski

Reputation: 4484

You can simply condition class to state, like this:

<div className={ this.state.exampleIsTruthy ? 'yourClass' : '' }>
  text
</div>

or if you want to switch classes based on a state like this:

<div className={ this.state.exampleTrueOrFalse ? 'shown' : 'hidden' }>
  text
</div>

Upvotes: 42

Orkun Tuzel
Orkun Tuzel

Reputation: 1432

If you need to add a conditional class to an existing class, this one may give you an idea

<span className={'fa ' + (this.state.dropdownActive ? 'fa-angle-up' : 'fa-angle-down')}></span>

in this example, I am showing an arrow icon for a dropdown depending on the state of the dropdown. I need to keep the class fa for any case to set the font-family of the span, and I only need to switch between fa-angle-up and fa-angle-down.

Same example with template literals

<span className={`fa ${this.state.dropdownActive ? 'fa-angle-up' : 'fa-angle-down'}`}></span>

Upvotes: 6

Ross Allen
Ross Allen

Reputation: 44900

The React documentation on manipulating class names suggests the classnames NPM package.

The docs for the package are great.

The following snippet is straight from the package README: Usage section

classNames('foo', 'bar');                 // => 'foo bar'
classNames('foo', { bar: true });         // => 'foo bar'
classNames({ 'foo-bar': true });          // => 'foo-bar'
classNames({ 'foo-bar': false });         // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: false, bar: true });    // => 'bar'

// lots of arguments of various types
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); 
// => 'foo bar baz quux'

// other falsy values are just ignored
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); 
// => 'bar 1'

Upvotes: 23

Alok Ranjan
Alok Ranjan

Reputation: 1097

The solution which is stated below by other author in above comment works for me

<div className={ this.state.end ? 'hidden' : 'shown' }>text</div>

Just a add on if you want to add more classes then add class separated by space.

Upvotes: 4

bmceldowney
bmceldowney

Reputation: 2305

For the record I think the classnames library answers are the most correct, but if you didn't want to pull in another dependency, you could roll your own simple implementation that works kind of like jQuery:

function getClassBuilder () {
    return {
        array: [],
        add: function (className) {
            if (this.array.indexOf(className) < 0) {
                this.array.push(className);
            }
        },
        remove: function (className) {
            var index = this.array.indexOf(className);
            if (index > -1) {
                this.array.splice(index, 1);
            }
        },
        toString: function () {
            return this.array.join(' ');
        }
    }
}

then, when you need to use it:

var builder = getClassBuilder();
builder.add('class1');
builder.add('class2');
if (condition) { builder.remove('class1') };

<a href="#" className={builder.toString()}>Button</a>

Upvotes: 3

Denis Ivanov
Denis Ivanov

Reputation: 905

Use Classnames library https://github.com/JedWatson/classnames

The classNames function takes any number of arguments which can be a string or object. If the value of the key is falsy, it won't be included in the output.

var classNames = require('classnames');

var Button = React.createClass({
  // ...
  render () {
    var btnClass = classNames({
      'btn': true,
      'btn-pressed': false,
      'btn-over': true
    });
    // output: btnClass = "btn btn-over"
    return <button className={btnClass}>{this.props.label}</button>;
  }
});

Take a look at the doc and let me know if you have any questions!

Cheers

Upvotes: 4

Mr. Benedict
Mr. Benedict

Reputation: 827

Ok, so I've been experimenting and it turns out there are ways and it's not as hard as I thought. This might help those just starting out in React JS.

So there are two ways of doing so and two reasons for adding in-line styles:

(1) Add class name inside a style attribute as an object so it can be styled inside a regular CSS stylesheet, directly inside a JSX file or used for conditional CSS

EXAMPLE 1

const classNameAsAPlainObject = {
        color: '#333333',
        backgroundColor: '#999999'
}

<a href="#" className="an-existing-class" style={classNameAsAPlainObject} >
Button
</a>

EXAMPLE 2

const conditionIsSomething = {
    color: 'red'
}
<a href="#" className="an-existing-class" style={conditionIsSomething ? 'classNameBasedOnCondition' : ' ' }>
Button
</a>

In the second example, two different classes can be declared depending on desired result or one class can be declared if condition is true or none if condition is false.

(2) Add it to the regular className attribute where a condition is required but be sure to accommodate for existing class names and be aware that this method requires styling in a regular CSS file. If no condition is required, then add the class as per normal to a className attribute.

EXAMPLE 3

<a href="#" className={"an-existing-class " + (conditionIsSomething ? 'thisClass' : 'thatClass')}>
Button
</a>

EXAMPLE 4

<a href="#" className={"an-existing-class " + (conditionIsSomething ? 'aClassIsAdded' : ' ')}>
Button
</a>

Again, if the condition requires it, one class can be declared or none as seen in example 4. Be sure to leave a space in either case after the "an-existing-class" and before the closing quote so there’s a space for the conditional class.

So I guess as a general rule of thumb, you're adding a class and styling as an object (as with Example 1 and 2), you can style it within the JSX file, but if adding a class name to the "className" attribute, you will be styling it inside a regular CSS file. I haven't experimented with this actually so I will give that a try. If anyone finds otherwise, please enlighten me.

Upvotes: -2

Related Questions