'Vanilla JavaScript: Is there a way to toggle multiple CSS-classes in one statement?

I use these JavaScript-code to change classes in my script:

var toggleDirection = function() {
  group.classList.toggle('left-to-right');
  group.classList.toggle('right-to-left');
}

In my example there a only two classes to change but could be also multiple classes ...

So therefore: Does anyone know a way to write the example less redundant?



Solution 1:[1]

No it is not possible using Element.classList API directly. Looking at API you can read:

toggle ( String [, force] ) When only one argument is present: Toggle class value; i.e., if class exists then remove it, if not, then add it. When a second argument is present: If the second argument is true, add specified class value, and if it is false, remove it.

Reference here.

You could potentially write your own "utility" function (in vanilla JS) which does what you want, below a very simple demonstrative example which work on top of the classList API:

var superToggle = function(element, class0, class1) {
  element.classList.toggle(class0);
  element.classList.toggle(class1);
}

And you call it in this way:

superToggle(group,'left-to-right', 'right-to-left');

Solution 2:[2]

For anyone looking for a short answer, you can do this on one line using the rest parameter introduced in ES6/ES2015:

const toggleCSSclasses = (el, ...cls) => cls.map(cl => el.classList.toggle(cl))

This is pretty close to @attacomsian's answer, but taking advantage of the fact that the rest parameter will return an array - no matter how many arguments is being passed to the function. Which means we can skip the part where we detect whether we're working with a string or an array.

const toggleCSSclasses = (el, ...cls) => cls.map(cl => el.classList.toggle(cl));

const one = document.querySelector(".one");

one.addEventListener("click", () => {
  toggleCSSclasses(one, "class1");
});

const two = document.querySelector(".two");

two.addEventListener("click", () => {
  toggleCSSclasses(two, "class1", "class2");
});
.class1 { text-decoration: underline }
.class2 { background: steelblue }
<p class="one">Click to toggle one class</p>
<p class="two">Click to toggle two classes</p>

Solution 3:[3]

just use the map array.

like

['left-to-right', 'right-to-left'].map(v=> group.classList.toggle(v) )

Solution 4:[4]

Here is ES6 version of solution

const classToggle = (el, ...args) => args.map(e => el.classList.toggle(e))

const classToggle = (el, ...args) => {
  args.map(e => el.classList.toggle(e))
}
.a {
  color: red
}

.b {
  background: black
}

.c {
  border-color: yellow
}
<button onclick="classToggle(this,'a', 'c','b')" class="a b c ">Click me</button>

And here's old JS code:

var classToggle = function classToggle(el) {
  for (
    var _len = arguments.length,
      args = new Array(_len > 1 ? _len - 1 : 0),
      _key = 1;
    _key < _len;
    _key++
  ) {
    args[_key - 1] = arguments[_key];
  }

  args.map(function (e) {
    return el.classList.toggle(e);
  });
};

Solution 5:[5]

You can extend the DOMTokenList object with the following multiToggle

if (window["DOMTokenList"]) //check if DOMTokenList is an existing object.
{
//multitoggle
DOMTokenList.prototype.multiToggle = function()
{
    if (arguments.length > 0) // there needs to be at least one object
    {
        for (argument in arguments) //loop all arguments
        {
            var argument = arguments[argument];
            //All primitives are allowed as input (Symbol not included). If not a primitive, raise error.
            if (Object.prototype.toString.call(argument) !== "[object Undefined]" && Object.prototype.toString.call(argument) !== "[object Null]" && Object.prototype.toString.call(argument) !== "[object String]" && Object.prototype.toString.call(argument) !== "[object Number]" && Object.prototype.toString.call(argument) !== "[object Boolean]")   
            {
                throw new SyntaxError;
            }
            else
            {
                if (this.contains(argument)) //check if classList contains the argument.
                {
                    this.remove(argument); //if so remove
                }
                else
                {
                    this.add(argument); //if not add
                }                   
            }
        }
    }
    else
    {
        throw new Error("The argument is not optional");
    }
    return undefined; //return undefined as with add and remove.
}       
}

multiToggle does not have the force ability of the original toggle. It just turns class names on and off for as many arguments as supplied.

Warning, expanding fixed Objects can cause troubles in the future . When an object gets deprecated or changed your functionality could break, requiring to more maintenance.

Solution 6:[6]

There is no direct way but you can create a helper function:

const toggleClass =  (el, cls) => {
    if (Array.isArray(cls)) {
        cls.map((cl) => {
            el.classList.toggle(cl);
        });
    } else {
        el.classList.toggle(cls);
    }
};

Now just call toggleClass() like below:

// single class
toggleClass(document.querySelector('body'), 'left-to-right');
//multiple classes
toggleClass(document.querySelector('body'), ['left-to-right', 'right-to-left']);

Solution 7:[7]

If I need to toggle multiple classes I just create an array and then iterate through it.

  var classes = [
    "red",
    "blue",
    "green",
    "purple"
  ]

  for (var i = 0; i < classes.length; i++){
    p.classList.toggle(classes[i])
  }

Solution 8:[8]

Assuming that myElement is a valid DOM Element, this works:

['right-to-left', 'left-to-right'].forEach(function(className){
  this.classList.toggle(className);
}, myElement);

Solution 9:[9]

This Worked for me

let superToggle = (element, class0, class1) => {
 element.classList.toggle(class0);
 element.classList.toggle(class1);
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Legends
Solution 2
Solution 3 NIKHIL CHANDRA ROY
Solution 4 M. Inam
Solution 5 Mouser
Solution 6 attacomsian
Solution 7 sado
Solution 8
Solution 9 user1744669