Jump to content
Search Community

clipPath Android Chrome Flicker-Bug

katerlouis test
Moderator Tag

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

Unfortunately I couldn't recreate the bug in a CodePen.

So I made a screencast.

 

The bug occurs on Chrome Android. iOS Safari is okay– The screencast is from a browserstack emulation with the exact same issue.

 

The issue occurs when I start tweening x or y WHILE CLIP-PATH is still tweening.

As soon as I get rid of x and y tweens, the flicker is gone!

 

https://www.dropbox.com/s/06st1azrxl6fyxi/GSAP clipPath.mov?dl=0

 

// Rough html layout
.menu
	nav
		a
		a
	.reservierungs-button
	.link-leiste

 

var master = new TimelineMax()

	.set(".menu", { height: "100%" })

	.set(slides, { display: "none" })
	.set(slides[slide], { clearProps: "display" })

	// CilpPath 
	.add("beforeClipPath")
	.to({ x: 0, elem: ".menu" }, .6, { x: 1, ease: Power3.easeOut, onUpdate: function() {
			var percent = this.target.x * 100;
			var clipPathString = (slide == 0)
				? "polygon(0% 0%, 100% 0%, 100% "+ percent +"%, 0% "+percent+"%)" // from top to bottom
				: "polygon(0% 100%, 100% 100%, 100% "+ (100 - percent) +"%, 0% "+ (100 - percent) +"%)" // bottom to top
			;
			TweenMax.set(this.target.elem, { webkitClipPath: clipPathString })
		}
	})
	.add("afterClipPath")
	.set(".menu", { clearProps: "webkitClipPath" }) // resolves the issue as soon as the clipPath is over, but not meanwhile.

	// the menu items
	.staggerFrom(".menu nav a", .8, { x:"-=200", opacity: 0, ease: Power4.easeOut }, .05, "-=.5")
	
	// the rest
	.fromTo(".reservierungs-button", .5, { x: "-=30", opacity: 0 }, { x: 0, opacity: 1 }, "-=.8")
	.fromTo(".link-leiste", .4, { y: "+=10", opacity: 0 }, { y: 0, opacity: 1 }, "-=.5")

	// topbar containing burger, icon fills and such
	.add(topBar(), (slide == 0) ? "beforeClipPath" : "afterClipPath-=.3")
;

 

In the CodePen (which doesn't recreate the main-issue, neither on phone nor desktop), I stumbled upon another odd behaviour when tweening x or y while clip-path is still tweening. This can be found in Chrome on desktop aswell. Maybe theres correlation?

 

See the Pen NvwOwb by katerlouis (@katerlouis) on CodePen

 

I wildly threw around with force3D and backface-visibility– 

But nothing changed.

 

I hope even under these hindered circumstances you can give some tips why this might be happening.

(hopefully not just a Chrome-bug that can't be circumvented)

Link to comment
Share on other sites

Sorry, not really familiar with the browser issues with clip-path. Last I checked IE / Edge didn't support it.

My assumption is that Chrome is just struggling somehow with the rendering.

 

Have you considered just animating the height of .div? seems to work well and gives the same effect:

 

See the Pen OjOKaG by GreenSock (@GreenSock) on CodePen

 

 

 

  • Like 3
Link to comment
Share on other sites

Hello, Do you have an actual code example link with this happening, since its not happening in codepen? Usually the same type of bug would show up in desktop chrome that happens on android mobile chrome. That is one good thing the chrome devs have implemented, making the same rendering at least for desktop PC chrome and mobile chrome on android. The fact it doesnt happen in codepen shows there is an issue with your original code somewhere.

 

Also when you see this flicker do you know if the element is animating using matrix3d() or just matrix() for the transform property inline on the element?

 

I believe it is only matrix() like your codepen above. As a rule of thumb anytime you animate x (translateX) or y (translateY) especially in Firefox desktop or mobile versions. Its best to add a slight rotation: 0.01 to prevent a firefox translation bug that could cause jank or flicker flack. That forces firefox to use matrix3d() so the element is placed on their own rendering layer for a smoother animation.

 

Along with making sure it uses transform matrix3d().. also sometimes adding backface-visibility:hidden on the problem element being transformed can help with this flicker.

 

But if you cant provide an example where this happens i would just opt for @Carl's solution animating the height of the div.

 

:)

  • Like 4
Link to comment
Share on other sites

I can't have animating the height. Everything inside is depending on the full height of the div. Flexbox children fighting for their space :D 

I tried an approach where I fake the clipPath idea; with a wrapper set overflow to hidden, and then animate it's height, while the inner container position to absolute holds the children .. but that lead to other bugs / inconveniences I can't have. 

 

I will try out Jonathans idea– 

And you are right, Jonathan, the bug also appears in Chrome on Mac.

Where exactly is backface-visibility to be placed? On the parent? The tweening child? 

 

If I can't solve this, I will upload to a stage and show you guys.

 

Thanks so far!

Link to comment
Share on other sites

Hello, You can either set backface-visibility : hidden via a GSAP set() before your regular tweens or on your to() or from() tween like

 

// GSAP will add webkit-backface-visibility if needed in webkit browsers
TweenLite.set(".element-with-transform", {backfaceVisibility:"hidden"});

 

or via your style-sheet

 

.element-with-transform {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

 

Usually that helps with the flicker bug, also adding transform-style: preserve-3d can help with that flicker along with backface-visibility: hidden. Those properties help the browser know the intent on how to render. Sometimes when they are missing the browser can render wrong since backface-visibility  default is visible and transform-style default is flat.

 

Also sometimes adding transform: translateZ(0) on the parent of the transformed element can help by bringing the parent on a new render layer like its transformed child.

 

:)

  • Like 1
Link to comment
Share on other sites

Thanks for the detailed explanation; 

I still wonder if these solutions need to be applied on the parent (the .menu being clip-path'd) or the items that are moved x / y wise (which is what causes the flicker- or atleast the flicker is gone when I don't tween x and y of the children)

 

backface-visibility seems to be for the transformed items, but what about transform-style and the minimal-rotation trick?

 

Carelessly trial and error with all combinations didn't work so far :D

Link to comment
Share on other sites

I now made sure that the (presumably causing) x-y-tweens all transform with matrix3d(). The raotationX: 0.01 trick made it happen. 

The clipMask still gets is cut off.

 

When I only transform one item inside the clipMask'd container, the clipMask is "repaired" by the time the transform tween is finished.

When I transform more than one item, the clipMask stays cut off, until I clear the prop entirely

It seems the cut-off is repaired when all the transformed children have a "clean matrix"?

 

.link-leiste in my case has a "somewhat dirty matrix" at the end of the tween.

EDIT: The "dirtiness" comes from the rotationX: 0.01 trick.

// .link-leiste inline-styles copied from Chrome dev tools "elements"
backface-visibility: hidden;
transform-style: preserve-3d;
opacity: 1;
transform: matrix3d(1, 0, 0, 0, 0, 1, 0.000174533, 0, 0, -0.000174533, 1, 0, 0, 0, 0, 1);

 

Here's the tween producing this matrix:

.fromTo(".link-leiste", .4, { y: "+=10", opacity: 0, transformStyle: "preserve-3d", backfaceVisibility:"hidden", rotationX: 0.01 }, { y: 0, opacity: 1 }, "-=.3")

 

This minor offset doesn't bother me visually at all. It appears to be layouted as expected.

 

But even if this "dirty matrix" would be resolved. It still cuts the clipMask for the time of its tweening.

 

EDIT:

So I am trying to force the parent (.menu) to just don't freak out when it's children transform :D

Putting all the tricks on the .menu doesn't work .. 

 

rotationX: 1.01, transform: translateZ(0), all result in a static transform on the .menu throughout the animation. But this doesn't change the cutOff throughout the childrens transform.

Link to comment
Share on other sites

SOLVED!

 

Deperately I tried to go in the exact opposite direction.

I stripped everything naked and force3D: false the transformed children.

 

Bam.

Profit.

 

// ClipMask on the parent
//..

// force children to transform with
// translate() or matrix() 

// NOT! translate3d() or matrix3d()

 

Without force3D: false the children transform with matrix3d– Why they do this is a mystery to me.

I assume that is the reason I couldn't recreate the issue on CodePen. The pen didn't use 3d()-methods.

 

 

Thank you very much Jonathan. Your encouragement to look into the actual transforming-method made me find what I needed.

Woop Woop!

 

 

PS: I don't mind the restriction of strict 2d in this case; but I wonder why Chrome doesn't like 3d in combination with a clipPath? Is this bug worth reporting? 

PSS: Sorry for the frequent posts; better to stay transparent and communicate for possible readers than.

  • Like 1
Link to comment
Share on other sites

Glad you got it sorted :)

 

If you have say a rotation on the element and tell GSAP force3D: false.. it might still use matrix3d() since your passing a rotation which can still tell GSAP to use matrix3D regardless if force3d is false. Did you have a rotation or z (translateZ) on your element as well?

 

You could report it to chrome webkit bug reports.

 

https://www.chromium.org/for-testers/bug-reporting-guidelines

https://webkit.org/reporting-bugs/

 

Sometimes also adding overflow:hidden to a 3d transformed element can make webkit-clip-path work. There previously was a webkit bug regarding this:

 

https://bugs.webkit.org/show_bug.cgi?id=95646

 

Even though its marked as fixed doesnt mean its really fixed, but that is the way of webkit. ;)

 

Also the spec shows for SVG elements when using clip-path that it will ignore clip-path if a 3d Transform is used, but not sure if this also applies to non SVG elements.

 

https://www.w3.org/TR/css-transforms-1/#svg-three-dimensional-functions

 

Happy Tweening :)

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