muaddoob

Tweening css classes

Recommended Posts

Have you considered adding the ability to tween between css classes?  Instead of specifying css properties in the tween, you could specify a css selector and it would tween anything defined in that class/id.  It would clean up the code and encourage reusability.  For instance, I have a lot of places where I'm tweening different elements to an "on" state.  I've defined the properties of that tween in a variable that I pass to each tween, but this seems like it would be more naturally handled in CSS.  It would also easily allow fallbacks to just toggling classes.

Share this post


Link to post
Share on other sites

You're in luck, Greensock already thought of this and it is a default part of CSSPlugin! From the API:
 
className - allows you to morph between classes on an element. For example, let's say myElement has a class of "class1" currently and you want to change to "class2" and animate the differences, you could do this:

TweenLite.to(myElement, 1, {className:"class2"});

And if you want to ADD the class to the existing one, you can simply use the "+=" prefix. To remove a class, use the "-=" prefix like this:

TweenLite.to(myElement, 1, {className:"+=class2"});

 
Note: there are some css-related properties that don't tween like IE filters and 3D transforms (support for those may come in the future). Also, there is a slight speed penalty when using className because the engine needs to loop through all of the css properties to see which ones are different.

  • Like 1

Share this post


Link to post
Share on other sites

Just two minor things to add:

  1. The note Jamie pasted in is outdated (not his fault - we needed to update the docs); 3D transforms should work great. 
  2. In version 1.8.3 and 1.8.4, you need to define the className inside a css:{} wrapper because DOM elements actually have a real property named "className" and the autoCSS feature that creates the css:{} wrapper automatically (for convenience) was missing one piece of conditional logic to ignore that. In the next update (coming very soon) that'll be fixed so that you don't need the css:{} wrapper around className. And to be clear, here's an example of the wrapper: 
    TweenLite.to(element, 1, {css:{className:"yourClass"}, ease:Power2.easeOut});

     

  • Like 2

Share this post


Link to post
Share on other sites

In a situation right now where I would like to tween a class and found this post. Am wondering, any way to remove the class once its been added? I'm thinking I will probably just need to define a second class that removes the properties in that were defined in the class that was added. But figured it was a question worth asking...

Share this post


Link to post
Share on other sites

Is is possible to remove multiple classNames like so? Or possibly by wildcard "unit-*"?

TweenMax.to(this.unit, 0.8, {
    className: "-=unit-focus -=unit-blur -=unit-offline -=unit-error -=unit-busy",
    ease: Expo.easeOut
});

Share this post


Link to post
Share on other sites

No, but you could run your own logic to analyze the current list of classes, tweak it however you need, and feed that list of classes to the tween. The relative values aren't meant to be stacked like that inside the tween. 

Share this post


Link to post
Share on other sites

Hi nitech  :)

 

to add or remove multiple classname you should insert white space between any two classname :

 

className:"+=class1 class2 class3"

  • Like 1

Share this post


Link to post
Share on other sites

Hi Diaco.AW ,

 

That's not entirely true, when the order of the classes doesn't match it does not work.

 

But I think that should be the expected behavior and I hope they include it soon.

Share this post


Link to post
Share on other sites

Hi angel.teran  :)

 

i see ; but you can use these methods to playing with classNames ,  i think we can do anything with out caring about the Classes orders :

TweenMax.to("#Box",1,{className:"+=class1 class2 class3"});

TweenMax.to("#Box",1,{className:"-=class1 class2 class3"});

TweenMax.to("#Box",1,{className:"-=class2"});

TweenMax.to("#Box",1,{className:"class3 class2 class1"});

TweenMax.set("#Box",{className:"class3 class2 class1"});

pls check this out :

 

http://codepen.io/MAW/pen/xbOWPz

Share this post


Link to post
Share on other sites

You could do something like this:

 

var tl1 = new TimelineMax()
tl1.to("#box1",3,{className:"box red wide round"})
    .to("#box1",3,{className:"box blue"});

 http://codepen.io/GreenSock/pen/gbwPqW

 

Keep in mind that if you have

<div class="red">

and you tween to className: "+=blue" the resulting div will be

<div class="red blue">

Which will most likely be confusing.

 

Also if you have 

<div class="box red"> 

and you tween to className:"blue" the resulting div will be

<div class="blue">

note that .box class got removed

 

Hopefully this helps you understand how and when className tweens should be used.

 

Happy Tweening!

  • Like 1

Share this post


Link to post
Share on other sites

This is excellent in that it animates the properties in the classes but I'm finding that it doesn't work as expected with staggering (TweenMax.staggerTo, ToFrom, and From). It's animating all of the items at once.

 

Is there a way to get this staggering classes too?

Share this post


Link to post
Share on other sites

Hi!

 

I have a problem where I want to Tween from an already set left and top offset ( set through Jquery and .offset({left: , top: }) ) to a specifik top and left offset set through a CSS-class, but what happens is nothing, but if I change the attribute in the CSS-file to !important then the left and top offset changes but they don't animate. Is there a way to get the Tween to work?

 

I have modified Diaco.AWs example to show my problem.

 

http://codepen.io/anon/pen/vOOXgB

 

What I'm trying to do is to crate a new <DIV> and position it over a clicked element (which can be at many different places) and then animate the <DIV> to a specific position (offset left: 0, offset top: 350) regardless of the position of the clicked elements position.

 

Best regards 

  Fredrik Johansson, Sweden

Share this post


Link to post
Share on other sites

This is just a specificity issue unrelated to GSAP. If you open dev tools, you'll see that GSAP is doing its job of applying the width properly (in animated fashion) to the inline CSS. However, if you add !important to the class, it overrides even the inline style, thus it jumps to that value and ignores all the changes GSAP is making during the animation. 

 

Without adding !important, the inline CSS that you applied using $(...).css({width:"100px"}); takes precedence. Thus, when GSAP adds the class, it correctly doesn't override the 100px width that you set inline. 

 

Is there a reason you need to animate to a className? I think you'd get better results if you just did normal tweens to the values you need. Not only is it faster, but it avoids the specificity issues you're running into. 

  • Like 1

Share this post


Link to post
Share on other sites

This is just a specificity issue unrelated to GSAP. If you open dev tools, you'll see that GSAP is doing its job of applying the width properly (in animated fashion) to the inline CSS. However, if you add !important to the class, it overrides even the inline style, thus it jumps to that value and ignores all the changes GSAP is making during the animation. 

 

Without adding !important, the inline CSS that you applied using $(...).css({width:"100px"}); takes precedence. Thus, when GSAP adds the class, it correctly doesn't override the 100px width that you set inline. 

 

Is there a reason you need to animate to a className? I think you'd get better results if you just did normal tweens to the values you need. Not only is it faster, but it avoids the specificity issues you're running into. 

 

Thanks for the respons!

 

The reasson I'm animating to a className is because it's easier to make a responsive site that way by using different implemented class names in different CSS-files for different sizes of the screen. Else i need to add some kind of check in my JavaScript which checks in what mode my website is, mobile or ordinary view, and I find that more complex.

Share this post


Link to post
Share on other sites

Hey Frim,

 

I struggled with this issue for a long time, and finally realized that the className tween is working correctly, my assumptions were wrong. Please read this thread to find out more.

 

http://greensock.com/forums/topic/11374-override-properties-when-tweening-classname/?p=46364

 

The demo I made in that thread uses the CSSRulePlugin to get the CSS values, which I then extend onto my target.

http://codepen.io/osublake/pen/gbjqbE

 

And if you're using media queries, you should check out the JavaScript way to do it.

http://codepen.io/osublake/pen/vExQEy

  • Like 1

Share this post


Link to post
Share on other sites

Yes, the problem had to do with the fact that you were targeting one element, but altering the class affected a completely different element altogether which wasn't the target of your tween. It wouldn't be intuitive to target one element and have the tween actually control a completely different element altogether. Actually, something like this could end up affecting tens or hundreds of other elements (as many descendants as the element has). 

 

Luckily, we did bake something into CSSPlugin that should be able to help. Again, this is a very unique (and quite uncommon) scenario and it wouldn't fit conceptually into the standard API, so it is in a CSSPlugin.cascadeTo() method. It spits back an array of TweenLite instances, one for each descendant that's affected. You can dump those into a timeline easily so that you can control them as a whole if you want. Here's how your code would look:

var tl = new TimelineMax({repeat:10, delay:0.5, repeatDelay:0.5, yoyo:true});
tl.add(CSSPlugin.cascadeTo(".start", 1, {className:"finish"}));

Does that help?

  • Like 2

Share this post


Link to post
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.