253

If I have class .A and class .B and want to switch in between on button click, what's a nice solution for that in jQuery? I still don't understand how toggleClass() works.

Is there an inline solution to put it in onclick="" event?

NLV
  • 21,141
  • 40
  • 118
  • 183
Stewie Griffin
  • 9,257
  • 22
  • 70
  • 97
  • 5
    Inline JS (`onclick=""`) is bad. why don't you use jQuery to register a proper event handler (or a delegate/live event if you have lots of elements with the same handler) – ThiefMaster Aug 09 '11 at 19:51

7 Answers7

592

If your element exposes class A from the start, you can write:

$(element).toggleClass("A B");

This will remove class A and add class B. If you do that again, it will remove class B and reinstate class A.

If you want to match the elements that expose either class, you can use a multiple class selector and write:

$(".A, .B").toggleClass("A B");
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • 3
    what if instead of element I want to put class A or B depending on the state? – Stewie Griffin Aug 09 '11 at 19:50
  • 1
    Be aware that you should cache the object you are trying to toggle rather than select the elements each time, the most common usage for toggling classes being in a click handler. ```var $trigger = $(".A"); $trigger.on("click", function() {$trigger.toggleClass("A B")});``` – mummybot Mar 27 '15 at 08:53
  • 1
    @mummybot - flagged as condescending. Frédéric - what if the element doesn't have any class "from the start"? that is an important state as well. – vsync Sep 21 '15 at 22:33
  • @vsync, that's another use case I think, but the usual solution works -- find a way to match the element, then decide which class you want to apply "at the start", then toggle afterwards. – Frédéric Hamidi Oct 02 '15 at 21:43
  • 4
    This does not work anymore. Now adds and removes both classes at the same time. – Fabián May 03 '18 at 01:35
  • @vsync and Frédéric have a good point but are being vague. For this to work properly you need your base-state class already set, the toggleClass(newState baseState) will remove it and add after but it needs to be present first. – acarito Jul 26 '18 at 21:07
  • @BurakUeda, can you elaborate more on this not working now? I just made a simple test in [this fiddle](https://jsfiddle.net/b2376wLo/) and it still seems to work, even with jQuery 3.3.1. – Frédéric Hamidi Dec 09 '19 at 09:31
  • 1
    @FrédéricHamidi I don't know what I did wrong but it wasn't working when I tried. Now it seems fine. In my case, it added and removed both classes at the same time but it seems working now. Probably I messed up something else and it affected this function. I deleted my comment. Sorry for the confusion. – BurakUeda Dec 12 '19 at 06:05
46

Here is a simplified version: (albeit not elegant, but easy-to-follow)

$("#yourButton").toggle(function() 
{
        $('#target').removeClass("a").addClass("b"); //Adds 'a', removes 'b'

}, function() {
        $('#target').removeClass("b").addClass("a"); //Adds 'b', removes 'a'

});

Alternatively, a similar solution:

$('#yourbutton').click(function()
{
     $('#target').toggleClass('a b'); //Adds 'a', removes 'b' and vice versa
});
Rion Williams
  • 74,820
  • 37
  • 200
  • 327
5

I've made a jQuery plugin for working DRY:

$.fn.toggle2classes = function(class1, class2){
  if( !class1 || !class2 )
    return this;

  return this.each(function(){
    var $elm = $(this);

    if( $elm.hasClass(class1) || $elm.hasClass(class2) )
      $elm.toggleClass(class1 +' '+ class2);

    else
      $elm.addClass(class1);
  });
};

// usage example:
$(document.body).on('click', () => {
  $(document.body).toggle2classes('a', 'b')
})
body{ height: 100vh }
.a{ background: salmon }
.b{ background: lightgreen }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
Click anywhere
vsync
  • 118,978
  • 58
  • 307
  • 400
4

Your onClick request:

<span class="A" onclick="var state = this.className.indexOf('A') > -1; $(this).toggleClass('A', !state).toggleClass('B', state);">Click Me</span>

Try it: https://jsfiddle.net/v15q6b5y/


Just the JS à la jQuery:

$('.selector').toggleClass('A', !state).toggleClass('B', state);
gdibble
  • 1,341
  • 14
  • 16
4

The easiest solution is to toggleClass() both classes individually.

Let's say you have an icon:

    <i id="target" class="fa fa-angle-down"></i>

To toggle between fa-angle-down and fa-angle-up do the following:

    $('.sometrigger').click(function(){
        $('#target').toggleClass('fa-angle-down');
        $('#target').toggleClass('fa-angle-up');
    });

Since we had fa-angle-down at the beginning without fa-angle-up each time you toggle both, one leaves for the other to appear.

Overcomer
  • 434
  • 5
  • 11
1

Here's another 'non-conventional' way.

  • It implies the use of underscore or lodash.
  • It assumes a context where you:
    • the element doesn't have an init class (that means you cannot do toggleClass('a b'))
    • you have to get the class dynamically from somewhere

An example of this scenario could be buttons that has the class to be switched on another element (say tabs in a container).

// 1: define the array of switching classes:
var types = ['web','email'];

// 2: get the active class:
var type = $(mybutton).prop('class');

// 3: switch the class with the other on (say..) the container. You can guess the other by using _.without() on the array:
$mycontainer.removeClass(_.without(types, type)[0]).addClass(type);
Luca Reghellin
  • 7,426
  • 12
  • 73
  • 118
1

Toggle between two classes 'A' and 'B' with Jquery.

$('#selecor_id').toggleClass("A B");

Love Kumar
  • 1,056
  • 9
  • 10