Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
mdolnik

Animating a CSS class swap

Recommended Posts

I am trying to animate back and forth between two css classes and I'm having some issues

 

right now I have two classes "contracted" and "expanded:

.button{
  border: 5px #000 solid;
}

.contracted{
  width:100px;
  height:100px;
  background-color:green; 
}

.expanded {
  width:200px;
  height:200px;
  background-color:red;
} 

And im trying to switch between them with:

$( ".button" ).click(function() {
  TweenMax.to(".contracted",2,{css:{className:"+=expanded"}}).set(".contracted",{delay:5,css:{className:"-=contracted"}});  
  
  TweenMax.to(".expanded",2,{css:{className:"+=contracted"}}).set(".expanded",{delay:5,css:{className:"-=expanded"}});
});

See the Pen vzayE by anon (@anon) on CodePen

 

And it will tween from "contracted" to "expanded"... but not vice-versa...

 

Is there a proper way to switch classes?

Link to comment
Share on other sites

Firstly, you can't chain tween function() calls like that ( TweenMax.to(...).set(...) ), since a tween is returned, which can't have further tweens added to it (you can definitely chain functions on timelines though). If you open the browser console you will see an error regarding the first .set() call. It would have to be changed to this to start working:

$( ".button" ).click(function() {
  TweenMax.to(".contracted", 2, { css:{ className:"+=expanded" } })
  TweenMax.set(".contracted", { delay:5, css:{ className:"-=contracted" } });  
  
  TweenMax.to(".expanded", 2, { css:{ className:"+=contracted" } })
  TweenMax.set(".expanded", { delay:5, css:{ className:"-=expanded" } });
});

Next, using 2 classes to apply this state is going to be problematic since expanded will always override contracted (following the cascade) so getting the correct starting and end values is difficult if you want to tween from "box contracted" to "box expanded" to "box contracted". It will be much easier if you avoid removing the contracted class, and just tween from "box contracted" to "box contracted expanded" to "box contracted".

 

And lastly, you are trying to create a tween on .contracted and .expanded at the same time, but CSSPlugin doesn't apply the target class until the end of the tween, so ".expanded" won't find the target of the first tween.

 

I hope I'm understanding your effect correctly; does something like this work better for you?

<div class="box contracted"></div>
<div class="contracted expanded"></div>
$( ".box" ).click(function() {
  // filter contracted so that unnecessary tweens on already .expanded aren't created
  var contracted = $(".contracted").not(".expanded");
  
  // include contracted as well since they aren't .expanded yet
  var expanded = contracted.add(".expanded");
  
  var tl = new TimelineLite();
  tl.to(contracted, 2, { className:"+=expanded" })
    .to(expanded, 2, { className:"-=expanded" }, 5)
});

Also, if it suits you, CSSPlugin does provide a way to directly swap to a new class but it's a complete replacement and would remove any other classes unrelated to the tween e.g.

tl.to(target, 2, { className:"expanded" })
  // targets only class will become .expanded (no .box)
  .to(target, 2, { className:"contracted" }, 5)
  // targets only class will become .contracted
  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×