Jump to content


Opacity Portion of staggerFromTo Skipped in TweenMax 1.19.1

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I'm looking for any suggestions as to what might cause the bug I'm currently experiencing in TweenMax 1.19.1 -- I've run out of ideas. Here are the basics:


  • I'm doing a TweenMax.staggerFromTo transformation that simply moves several elements from -20px and 0 opacity to 0px and 1 opacity. The classic "fade in from the left."
  • The animation runs perfectly except that, with the most recent update to TweenMax, the opacity portion of the tween is being skipped altogether.
  • The opacity of the elements is never modified and, even with clearProps not being used, opacity is not left in the Styles attribute after the transformation.
  • The result is that the elements appear on the screen, then move 20 pixels to the right in sequence with no fade in.


Some additional information:

  • This bug appears in 1.19.1 only. I can switch back to TweenMax 1.19.0 and it won't appear, switch again to 1.19.1 and it will. So it's something that changed between this version and the last.
  • I've tested in on Chrome and Firefox so it isn't just a single browser.
  • While I've copied the basic situation in a Codepen, I cannot seem to reproduce the bug. There's a lot going on on this page, but no other modifications to this element take place before the Tween with the problem. I've tried adding every CSS attribute assigned to the real element to the Codepen element and I've reproduced the nested function/promise/function structure of the js, but I can't get the issue to appear. The attached pen does show the context, at least.
  • If I set the debugger to break on attribute modification, in 1.19.0 it breaks first on the opacity part of CSSPlugin.js at line 2611. In 1.19.1 it breaks on the matrix portion of CSSPlugin.js at line 1722, skipping the opacity code entirely.
  • If I try to modify only the opacity and not the position, it does nothing at all and no attributes are modified on that element. It's definitely only the opacity tween that's affected.


Any thoughts on what has changed in 1.19.1 that could lead to opacity being skipped in a staggerFromTo under certain conditions? I'd prefer not to have to freeze Greensock updates on this project and stay with 1.19.0 for good, but I've spent more than a day on this and I still can't figure out what might be causing this deeply obscure problem.

See the Pen jyQZMJ by jonathansousa (@jonathansousa) on CodePen

Link to comment
Share on other sites

Hi BaskingShark  :)


Welcome to the GreenSock forum.


I'm a little confused. I just looked at your pen in Chrome, Edge, IE11 & FF using 1.19.0 and 1.19.1 and everything was fine. I know you said it wasn't appearing in the CodePen demo, but I just wanted to verify that it was working in all browsers and both GSAP versions.


I don't know if anything was changed from 1.19.0 to 1.19.1 that may cause that. For that answer we'd have to kick this upstairs to Carl or Jack. 


Without seeing the problem in the demo, I'm not sure what to tell you.


The big guns should be along shortly and may have more information.


Happy tweening.


  • Like 1
Link to comment
Share on other sites

Yeah, I know it's not helpful to be unable to duplicate it in a CodePen, but I'm hoping that one of the developers can think of the possible triggers for skipping opacity in a tween and if any of those changed in this TweenMax update. I've simply run out of ideas on what is causing it to skip that portion of the code since it doesn't seem to be either the CSS or the immediate JS. Since there are thousands of lines of Javascript that make up the entire web app, I'm hoping for a hint about other places to look for what could be the cause.


Thanks for checking!

  • Like 1
Link to comment
Share on other sites

Hello BaskingShark and welcome to the GreenSock forum!


Since you are using a from tween, in this case staggerFromTo(). You have to keep in mind that from() tweens will render immediately by default. Also make sure you are always using the latest version of GSAP.


Does this resolve your issue:


See the Pen dNaqog by jonathan (@jonathan) on CodePen


So you can try a couple of things.

  • You can add the special property immediateRender:false to your tween:
    See the staggerFromTo() docs: https://greensock.com/docs/#/HTML5/GSAP/TweenMax/staggerFromTo/

    immediateRender:  Normally when you create a tween, it begins rendering on the very next frame (update cycle) unless you specify a delay. However, if you prefer to force the tween to render immediately when it is created, setimmediateRender to true. Or to prevent a from() from rendering immediately, set immediateRender to false. By default, from() tweens set immediateRender to true.
  • Instead of using opacity you can use the GSAP special property autoAlpha for better performance, which is part of the CSSPlugin:
    See the CSSPlugin docs: https://greensock.com/docs/#/HTML5/GSAP/Plugins/CSSPlugin/

    autoAlpha: Identical to opacity except that when the value hits 0 the visibility property will be set to "hidden" in order to improve browser rendering performance and prevent clicks/interactivity on the target. When the value is anything other than 0, visibility will be set to "inherit". It is not set to "visible" in order to honor inheritance (imagine the parent element is hidden - setting the child to visible explicitly would cause it to appear when that's probably not what was intended). And for convenience, if the element's visibility is initially set to "hidden" and opacity is 1, it will assume opacity should also start at 0. This makes it simple to start things out on your page as invisible (set your css visibility:hidden) and then fade them in whenever you want.
    //fade out and set visibility:hidden
    TweenLite.to(element, 2, {autoAlpha:0});
    //in 2 seconds, fade back in with visibility:visible
    TweenLite.to(element, 2, {autoAlpha:1, delay:2});
  • And when you use autoAlpha with a from tween (staggerFromTo()) you would also add to your .box CSS rule visibility:hidden. This way your elements will be hidden when the page loads so you dont see your elements flash in visible when they should start with the elements hidden and then fade in.

CSSPlugin docs: https://greensock.com/docs/#/HTML5/GSAP/Plugins/CSSPlugin/
staggerFromTo() docs: https://greensock.com/docs/#/HTML5/GSAP/TweenMax/staggerFromTo/


Happy Tweening :)

  • Like 1
Link to comment
Share on other sites

OK, this is good: while immediateRender:false doesn't help, autoAlpha seems to work under both 1.19.0 and 1.19.1!


When I watch for DOM attribute modification, the first break in JS with autoAlpha under 1.19.1 happens at the same point as that for opacity under 1.19.0: line 2611 in CSSPlugin. It seems that the problematic pathway through that plugin is corrected with autoAlpha and the opacity portion of the tween is no longer skipped. I think there's a deep, obscure bug somewhere in TweenMax relating to skipping opacity, but it seems it can be bypassed with autoAlpha. I can run identical code under 1.19.0 and 1.19.1 with the only difference being "opacity" or "autoAlpha" -- the first jumps past the opacity tween code, the second activates it.


I wish I could isolate the problem in a Codepen since I'm sure other people could benefit if the root cause could be found, but for now this solves the issue and lets me keep working.



  • Like 1
Link to comment
Share on other sites

Hello BaskingShark glad you got it sorted :D


I would also recommended to remove will-change: color from your CSS.


The will-change CSS property is really a last resort type of CSS property. It is only needed when the browser is rendering wrong to begin with. I commented it out and didn't notice any rendering issue with the CSS color property and with only using opacity and not autoAlpha.


The CSS will-change is really only needed for CSS properties like: opacity, transforms, and position offsets like top, right, bottom, and left.


So the issue you are probably seeing with opacity is probably being caused by the will-change CSS property, even though you are only targeting color. So in your case you don't even need to use it ;)


CSS property will-change: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change



  • Like 1
Link to comment
Share on other sites

Just ran a test and will-change doesn't make a difference in the opacity bug -- it still skips that portion of the CSSPlugin code -- but autoAlpha works in either case. I'll stick with that.


Still, I'm removing that will-change and a few others; thanks! The way that browsers are now implementing that property makes it far less useful than it used to be for improving performance. It's moved from a useful hint to toss elements over to the GPU for faster processing to one that acts more like an !important flag for browser rendering... not terribly helpful in most cases.

Link to comment
Share on other sites

BaskingShark, I forgot to ask what is the OS version and browser version you are seeing this opacity shenanigans in?

Link to comment
Share on other sites

I've seen the same behavior on macOS 10.12.3 with both Chrome 56.0.2924.87 and Firefox 51.0.1.



Link to comment
Share on other sites

OK, I finally tracked down the bug and modified my original Codepen to demo it. The issue is with the updated _addPropTween function on TweenMax's line 6984. It's an obscure one for sure:


  • When you set opacity on an element and also set a css class, like 
    var tl = new TimelineMax().set(obj, {opacity: 0, css: {className: '+=active'}});
     the new _addPropTween function mistakenly adds opacity to that DOM element's properties.
  • Then if that element is tweened later on and opacity is one of the css properties being manipulated, TweenMax's line 6866 
    if (!_reservedProps[p] && (!(p in target) || p === "transform" || p === "x" || p === "y" || p === "width" || p === "height" || p === "className" || p === "border") && (!_plugins[p] || (_plugins[p] && _plugins[p]._autoCSS)))

    finds opacity in the target and doesn't add it to vars.css. It gets skipped.


Maybe this is now the desired behavior? I tend to think that adding a non-standard property to a DOM element is probably going to cause other problems down the line, like it did in my case.


Whew! That was a monster to find.

Link to comment
Share on other sites

This doesn't look like a bug to me...

var tl = new TimelineMax().set(obj, {opacity: 0, css: {className: '+=active'}});

When you add a css object like that, ALL your css properties need be inside that object. Anything outside of that object will be considered a property of the element.

// Works
var tl = new TimelineMax().set(obj, { css: { opacity: 0, className: '+=active'}});

// Also works, implicit css for elements 
var tl = new TimelineMax().set(obj, { opacity: 0, className: '+=active'});

You can read about the autoCSS feature in the docs.



  • Like 3
Link to comment
Share on other sites

Nice Blake you beat me to it. I was going to suggest the same thing.


What you describe is not a bug. The opacity property in your code example above needs to go inside the css:{} object if you specify it in your tween. It's best to just not add the css:{} object and allow GSAP to build the css:{} object for you.



  • Like 1
Link to comment
Share on other sites

While i absolutely agree this is sloppy syntax — the result of weeks of editing and re-edting a massive web app — it’s also a structure that was fully supported until this point release. And one that works with the aim of autoCSS to provide a shortcut for frequently animated css properties. It seems to me that either the documentation needs to be updated to explicitly warn against mixing css and autoCSS properties, or the code needs to continue to support a combination within a single statement as it has until 1.19.1.


I just figure that if this situation showed up for me and broke a fully tested web app, then it’s bound to hit other people as well and similarly mystify them.

Link to comment
Share on other sites

Hello agian BaskingShark


Regarding autoCSS .. in your case you are using opacity outside the css:{}, that you are defining manually in your tween. GSAP would know that opacity is a CSS property so there would be no need to use autoCSS in this case.


But i can see where the confusion could happen, Sorry for any confusion, we will try and explain the reasoning! :blink:;)


You can find the following in the CSSPlugin Docs:


  • Note about css:{} wrapper
    Originally, css-specific properties needed to be wrapped in their own object and passed in like TweenLite.to(element, 1, {css:{left:"100px", top:"50px"}}); so that the engine could determine the properties that should be funneled to CSSPlugin, but because animating DOM elements in the browser is so common, TweenLite and TweenMax (as of version 1.8.0) automatically check to see if the target is a DOM element and if so, it creates that css object for you and shifts any properties that aren't defined directly on the element or reserved (like onComplete, ease, delay, etc. or plugin keywords like scrollTo, easel, etc.) into that css object when the tween renders for the first time. In the code examples below, we'll use the more concise style that omits the css:{} object but be aware that either style is acceptable.
//as of 1.8.0 the following lines produce identical results:
TweenLite.to(element, 1, {top:"20px", backgroundColor:"#FF0000", ease:Power2.easeOut});
//longer, less convenient syntax:
TweenLite.to(element, 1, {css:{top:"20px", backgroundColor:"#FF0000"}, ease:Power2.easeOut});

Please standby and we will be able to explain this better, again sorry for any confusion.



  • Like 1
Link to comment
Share on other sites

Yep, Jonathan and Blake are correct - as far as I can tell this is not a bug at all and I'm actually quite surprised that your original code worked at all in previous versions. It shouldn't. The whole point of defining a css:{} object is to tell GSAP specifically "these are my CSS-related properties" so that it can skip all the logic that it normally has to run to try to figure out which ones are CSS and which ones are direct properties on the object itself. 


You were defining opacity as specifically NOT a css-related property originally, so GSAP was like "okay, I'll set that directly on your element (rather than as a CSS property)". Thereafter, other autoCSS tweens of opacity would notice that there's an "opacity" property directly on the element itself and prefer that instead of CSS. 


This is all expected behavior and from what I can tell, it's in line with what's explained in the docs but let me know if you have any specific ideas to improve the docs. I don't remember anyone else running into something like this in the past, so it doesn't strike me as a common mis-step that points to a deficiency in the docs, but I may be missing something. Totally open to suggestions. 

  • Like 2
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.