Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Pete Barr

css animation-fill-mode prevents GSAP from working

Recommended Posts

Hi,

 

Has anyone come across this before where an svg element that's been animated with CSS animation and has the animation-fill-mode: forwards applied to it means that GSAP can't animate that element's property?

 

What I'm trying to achieve is an animated preloader that animates in via css animation, so that it's lightweight and GSAP doesn't have to load in the document head, but when the app fully loads GSAP is used to animate it out with a more complex animation.

 

However…

 

In the codepen example used, the marker is initially positioned outside it's native svg position, then after 0.5 sec it animates back to its native position. However to get the marker to remain in that position at the end of the animation it requires 'animation-fill-mode: forwards' otherwise it jumps back down. I've added a basic GSAP tween to simulate a window.load function by just adding a 2 second delay, to animate it up after the css animation has finished, but it doesn't animate due to this css property being added. You can see the console is logging out at the end of the 'non moving' GSAP animation.

 

Any ideas folks? Or do I deserve a banana award today for being dim? I am very tired today :-(

 

Cheers,

 

Pete.

See the Pen 3ca350a215a9b7254201d6e17dadad9e by petebarr (@petebarr) on CodePen

Link to post
Share on other sites

I think that's how it supposed to work. Forwards keeps whatever value it animated on there. If you look at the computed properties in the console, you'll see that it's still running.

 

But what I'm wondering about is the reason for your lightweight approach. How much time passes between the head and the closing body tag? Or is this a hunch?

 

Loading libraries from a CDN will cache a version on the user's browser, so that can improve your load time. And have you looked into using a service worker to hydrate your app. Google's sw-precache module is pretty popular.

https://github.com/GoogleChrome/sw-precache

  • Like 2
Link to post
Share on other sites

Hello Pete Barr,

 

If it was me doing this i would have a separate class for your CSS animation with the animation-fill-mode. And then either have that class on the element when the animation completes using the animationend event handler. Then when that CSS animation is complete, you  remove the class with that CSS animation. Then just animate with GSAP as usual.

 

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

 

The JS:

var loaderTl = new TimelineMax(),
	element = document.querySelector(".marker");

// listen for CSS animationend event handler
element.addEventListener("animationend", gsapAnimation, false);

function gsapAnimation() {
	console.log('CSS animation complete');
	// remove CSS animation class
	element.classList.remove("css-anim");
	// run GSAPJS animation
	loaderTl.to('.marker', 1, {
		y: -100,
		delay: 2,
		onComplete: function() {
			console.log('GSAPJS animation complete')
		}
	});
}

Your  SVG DOM element has an extra class css-anim solely for the CSS animation:

<circle class="marker css-anim" cx="163" cy="163" r="23" fill="#d60d0d"/>

And the CSS targeting only .marker.css-anim so when .css-anim is removed any CSS animation will no longer be associated due to the class only being .marker and not .marker.css-anim

.marker.css-anim {
    animation: markerAnim 0.5s 0.5s cubic-bezier(0.120, 0.900, 0.280, 1.175);
    transform-origin: center center;
    animation-fill-mode: forwards;
    transform: translateY(100px);
}

You want to be careful about mixing CSS animation with GSAP since both will be competing to animate the same element.. like a tug of war.

 

But if it was me i would do it all with GSAP.

 

Resources:

animationend: https://developer.mozilla.org/en-US/docs/Web/Events/animationend

 

:)

  • Like 2
Link to post
Share on other sites

I think that's how it supposed to work. Forwards keeps whatever value it animated on there. If you look at the computed properties in the console, you'll see that it's still running.

 

But what I'm wondering about is the reason for your lightweight approach. How much time passes between the head and the closing body tag? Or is this a hunch?

 

Loading libraries from a CDN will cache a version on the user's browser, so that can improve your load time. And have you looked into using a service worker to hydrate your app. Google's sw-precache module is pretty popular.

https://github.com/GoogleChrome/sw-precache

 

 

The lightweight approach was so that I have skinny code in the head for the preloader animation allowing it to animate while waiting for the window load which would include custom js, tweenmax, and any other libraries we are going to use before the closing body.

 

To be honest I haven't a scooby about service workers ;-)

Link to post
Share on other sites

Cheers Jonathan, that's exactly what I should have done. Doh! I was kinda holding out for a simple css solution.

 

Anyway, I've already binned that CSS animation idea and am just going with straight up GSAP. My eye was starting to twitch.

 

Long live the king! ;-)

  • Like 3
Link to post
Share on other sites

Great solution, Jonathan!

 

Pete, a general rule of thumb is to avoid mixing any CSS animations / transitions with GSAP as they will most likely be competing for control over the same properties. 

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

×