Jump to content
Search Community

SplitText character "jerkiness" issue in Chrome

Vitalii Bahmet test
Moderator Tag

Go to solution Solved by Jonathan,

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

Hi dear devs and coders,

 

Please have a look at provided CodePen sample. I'm having/seeing issue - jerky animation of characters - with SplitText in Chrome every time I use it. Especially that's noticeably with slight transforms and on non-Retina display.

 

Not sure maybe I've missed some Chrome spec or tip for solving that.

 

Please help :)

 

Cheers

Vitaliy

See the Pen yVqYdP by bagmetv (@bagmetv) on CodePen

Link to comment
Share on other sites

  • Solution

Hello Vitaliy Bagmet and welcome to the GreenSock forum!

 

Ok the following should be more smooth and less jitter jank now. Tested on windows 10 lasted Chrome.

 

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

 

Normally this can be fixed with just a slight rotation, but since it is Chrome it suffers from various browser bugs. Especially when translating text in small increments. Sometimes you have to force Chrome to play nice.

 

Try adding the following 5 CSS properties to your tweens that animate SplitText

  • translateZ()
  • rotate()
  • transform: perspective()
  • transform-style
  • backface-visibility

GSAP syntax of the above CSS properties:

z: 0.01, /* force matrix to matrix3d() and to make smooth */
rotation:0.01, /* offset slightly to make smooth */
transformPerspective: 1000, /* add this to force right perspective even though a 2D effect */
transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */

So it should look like this for those SplitText tweens functions:

function footerSplitFunc2() {
        var tl = new TimelineMax();
        tl.staggerFrom(footerSplit2.chars, 0.75, 
        {
          transformOrigin: "50% 100%", 
          autoAlpha: 0, 
          scale: 0, 
          x: 20, 
          z: 0.01, /* force matrix to matrix3d() and to make smooth */
          rotation:0.01, /* offset slightly to make smooth */
          transformPerspective: 1000, /* add this to force right perspective even though a 2D effect  */
          transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
          backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */
          ease: Power1.easeOut
        }, 0.02);
        return tl;
}

function footerSplitFunc3() {
        var tl = new TimelineMax();
        tl.staggerFrom(footerSplit3.chars, 0.75, 
        {
          transformOrigin: "50% 100%", 
          autoAlpha: 0, 
          scale: 0, 
          x: 20, 
          z: 0.01, /* force matrix to matrix3d() and to make smooth */
          rotation:0.01, /* offset slightly to make smooth */
          transformPerspective: 1000, /* add this to force right perspective even though a 2D effect  */
          transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
          backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */
          ease: Power1.easeOut
        }, 0.02);
        return tl;
}

function footerSplitFunc4() {
        var tl = new TimelineMax();
        tl.staggerFrom(footerSplit4.chars, 0.75, 
        {
          transformOrigin: "50% 100%", 
          autoAlpha: 0, 
          scale: 0, 
          x: 20, 
          z: 0.01, /* force matrix to matrix3d() and to make smooth */
          rotation:0.01, /* offset slightly to make smooth */
          transformPerspective: 1000, /* add this to force right perspective even though a 2D effect  */
          transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
          backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */
          ease: Power1.easeOut
        }, 0.02);
        return tl;
}

I did add a slight rotation: 0.01 to some of your tween that were translating in y or x since that can help in Firefox. But you could also add force3D:true to some of your non text elements tweens to make them use translate3d() or matrix3d() to get more smooth movement if needed.

 

I did not test on retina display (apple 5k) since i do not have one available .

 

I hope this helps! :)

  • Like 5
Link to comment
Share on other sites

Yep, Chrome has introduced some really odd (BAD) rendering behavior, some of which I detailed in this article: http://greensock.com/will-change/. The Chrome team insists these are "improvements" but I strongly disagree. 

 

In your demo, things seemed to look better in Chrome is I set CSSPlugin.defaultForce3D = false. Does that help? 

  • Like 3
Link to comment
Share on other sites

Hello Vitaliy Bagmet and welcome to the GreenSock forum!

 

Ok the following should be more smooth and less jitter jank now. Tested on windows 10 lasted Chrome.

 

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

 

Normally this can be fixed with just a slight rotation, but since it is Chrome it suffers from various browser bugs. Especially when translating text in small increments. Sometimes you have to force Chrome to play nice.

 

Try adding the following 5 CSS properties to your tweens that animate SplitText

  • translateZ()
  • rotate()
  • transform: perspective()
  • transform-style
  • backface-visibility

GSAP syntax of the above CSS properties:

z: 0.01, /* force matrix to matrix3d() and to make smooth */
rotation:0.01, /* offset slightly to make smooth */
transformPerspective: 1000, /* add this to force right perspective even though a 2D effect */
transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */

So it should look like this for those SplitText tweens functions:

function footerSplitFunc2() {
        var tl = new TimelineMax();
        tl.staggerFrom(footerSplit2.chars, 0.75, 
        {
          transformOrigin: "50% 100%", 
          autoAlpha: 0, 
          scale: 0, 
          x: 20, 
          z: 0.01, /* force matrix to matrix3d() and to make smooth */
          rotation:0.01, /* offset slightly to make smooth */
          transformPerspective: 1000, /* add this to force right perspective even though a 2D effect  */
          transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
          backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */
          ease: Power1.easeOut
        }, 0.02);
        return tl;
}

function footerSplitFunc3() {
        var tl = new TimelineMax();
        tl.staggerFrom(footerSplit3.chars, 0.75, 
        {
          transformOrigin: "50% 100%", 
          autoAlpha: 0, 
          scale: 0, 
          x: 20, 
          z: 0.01, /* force matrix to matrix3d() and to make smooth */
          rotation:0.01, /* offset slightly to make smooth */
          transformPerspective: 1000, /* add this to force right perspective even though a 2D effect  */
          transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
          backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */
          ease: Power1.easeOut
        }, 0.02);
        return tl;
}

function footerSplitFunc4() {
        var tl = new TimelineMax();
        tl.staggerFrom(footerSplit4.chars, 0.75, 
        {
          transformOrigin: "50% 100%", 
          autoAlpha: 0, 
          scale: 0, 
          x: 20, 
          z: 0.01, /* force matrix to matrix3d() and to make smooth */
          rotation:0.01, /* offset slightly to make smooth */
          transformPerspective: 1000, /* add this to force right perspective even though a 2D effect  */
          transformStyle:"preserve-3d", /* let the browser know this is 3d effect */
          backfaceVisibility:"hidden", /* make sure when 3d is applied it doesnt bleed over */
          ease: Power1.easeOut
        }, 0.02);
        return tl;
}

I did add a slight rotation: 0.01 to some of your tween that were translating in y or x since that can help in Firefox. But you could also add force3D:true to some of your non text elements tweens to make them use translate3d() or matrix3d() to get more smooth movement if needed.

 

I did not test on retina display (apple 5k) since i do not have one available .

 

I hope this helps! :)

 

 

Hi Jonathan,

 

Wow! Thank you so much for detailed comments and updated sample!

All is absolutely clear and works great on non-Retina display (and on iMac 5K too of course)!

 

Many many thanks once again!

 

Cheers

Vitaliy

Link to comment
Share on other sites

Yep, Chrome has introduced some really odd (BAD) rendering behavior, some of which I detailed in this article: http://greensock.com/will-change/. The Chrome team insists these are "improvements" but I strongly disagree. 

 

In your demo, things seemed to look better in Chrome is I set CSSPlugin.defaultForce3D = false. Does that help? 

 

 

Hi Jack,

 

Many thanks for your response!

Yes, setting that to false  is just slightly better though it doesn't solve visual lags as they are.

But of course all these CSS 3D transform "tweaks" by Jonathan together produce great result.

 

Cheers

Vitaliy

  • Like 1
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.
×
×
  • Create New...