Motion Paths – Past, Present and Future

Making animations that “feel right” can be tricky.

When I’m stuck, I find Disney’s 12 principles of animation useful. They’re from the book ‘The Illusion of Life’ and although the book was written about hand-drawn character animation, a lot of the principles are relevant for animation on the web.

The 7th principle of animation is about arcs:

Most natural action tends to follow an arched trajectory, and animation should adhere to this principle by following implied “arcs” for greater realism.

In other words, animating along a curved path can make movement feel more realistic.

Straight lines are what browsers do best though. When we animate an element from one place to another using a translation the browser doesn’t take realism into account. It’ll always take the fastest and most efficient route.

This is where motion paths can come in handy. Motion paths give us the ability to move an element along a predefined path. They’re great for creating trajectories to animate along.

Use the toggle to see the paths.

See the Pen Alien Abduction- toggle by Cassie Evans (@cassie-codes) on CodePen.default

As well as being useful, they’re quite a lot of fun to play around with.

See the Pen Loop by Cassie Evans (@cassie-codes) on CodePen.default

So, how do you animate along a motion path?

I use GreenSock (GSAP) for most of my SVG animation and I made these demos using the newly released GSAP 3 and their MotionPathPlugin. So, if you want to skip to that bit, go ahead!

Otherwise let’s take a little journey through the past, present and future of motion path animation.

(Did someone say CSS motion paths?)

First, a little setup tip.

Make sure to keep the path and element you’re animating in the same SVG and co-ordinate space, otherwise things get a bit messy.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1300 800">
  <path class="path" d="M1345.7 2.6l2.4-4.4"/>
  <g class="rocket">
    ...
  </g>
</svg>

SMIL

If you google “SVG motion path animation”, you’re going to get a lot of hits talking about SMIL.

SMIL was the original proposed method for SVG animation. It included the ability to animate along a path using the <animatemotion> element.

It’s nice and declarative and currently the browser support is surprisingly good, covering all modern browsers except Edge and Opera Mini.

But, and this is a big but, the future of SMIL is uncertain, and has been for a while.

It was deprecated by Chrome a few years back and although they’ve now suspended that deprecation, implementations still vary and there’s no clear path towards cross-browser support.

Although it’s fun to play around with, SMIL isn’t very future-proof, so I’m only going to touch on it.

In order to animate along a path with the animateMotion element, you reference the path you want to animate along using path="..." and define the element you want to animate using xlink:href="#...":

<animateMotion 
    path="M20.2..."
    xlink:href="#rocket" 
    dur="10s" 
    rotate="auto"
    
/>

See the Pen loop SMIL by Cassie Evans (@cassie-codes) on CodePen.default

With SMIL effectively out of the picture, browser vendors are now focused on supporting modern alternatives like the CSS Motion Path Module.

CSS Motion Path Module

Attention: As of the time of writing, the examples in this section are experimental and best viewed in Chrome.

You can check out which features your browser supports in the demo below.

See the Pen Browser Support – CSS motion path module by Cassie Evans (@cassie-codes) on CodePen.default

If you’ve got all green smiley faces, you’re good to go. But you may have a sad face for offset-anchor. This is because this property is currently still experimental. It’s behind a flag in Chrome, meaning it’s not turned on by default.

You can choose to enable it by going to this URL in Chrome:

chrome://flags/#enable-experimental-web-platform-features

and enabling experimental web platform features.

This module is joint work by the SVG and CSS working groups, so unlike SMIL, we’ll be able to use CSS motion paths to animate both, HTML and SVG DOM elements. I love a CSS-only solution, so although it’s not ready to use in production (yet), this is pretty exciting stuff.

The motion path module consists of five properties:

  • offset (shorthand property for the following)
  • offset-path
  • offset-distance
  • offset-anchor
  • offset-rotate

offset-path

offset-path defines the path that we can place our element on. There are a few proposed values but path() seems to be the only one supported right now.

.rocket {
	offset-path: path('M1345.7 2.6l2.4-4.4');
}

path() takes a path string with SVG coordinate syntax, which may look scary, but you don’t have to write this out. You can create a path in a graphics editing program and copy and paste it in.

offset-distance

offset-distance specifies the position along an offset-path for an element to be placed. This can be either in pixels or as a percentage of the length of the path.

See the Pen Rocket – CSS motion path – offset-distance by Cassie Evans (@cassie-codes) on CodePen.default

offset-anchor

By default the element’s top left corner will be aligned with the path, but we can change this with offset-anchor.
offset-anchor behaves a lot like transform-origin. In fact if set to auto, it’s given the same value as the element’s transform-origin, so we can optionally use transform-origin for the same results.

Like transform-origin it accepts a position with x and y values, either as a percentage or a keyword like bottom or left.

Have a play with the values:

See the Pen Rocket – CSS motion path – offset anchor by Cassie Evans (@cassie-codes) on CodePen.default

offset-rotate

offset-rotate defines the direction the element faces on the path.

By default it’s set to auto and will rotate with the path. You can pass in an optional second value in degrees in order to tweak the direction of this rotation.

See the Pen Rocket – CSS motion path – offset-rotate – auto deg by Cassie Evans (@cassie-codes) on CodePen.default

If you want your element to face the same direction throughout, and not rotate with the path, you can leave out auto and pass in a value in degrees.

See the Pen Rocket – CSS motion path – offset-rotate – deg by Cassie Evans (@cassie-codes) on CodePen.default

These properties were renamed from motion to offset since this spec was proposed. This is because alone, these properties just provide another way to set the position and rotation of absolutely positioned elements. But we can create motion by using them in conjunction with CSS animations and transitions.

.rocket {
  offset-path: path('M20.2...');
  offset-anchor: 50% 50%;
  offset-rotate: auto;
  /*   if offset anchor isn't supported we can use transform-origin instead */
  transform-origin: 50% 50%;
  animation: move 8s forwards linear;
  transform-box: fill-box;
}

@keyframes move {
  from {
    offset-distance: 0%;
  }
  to {
    offset-distance: 100%;
  }
}

See the Pen Rocket – CSS motion path by Cassie Evans (@cassie-codes) on CodePen.default

Attention: SVG transform-origin quirks.

In this demo, I’m using a relatively new CSS property, transform-box.

This is to avoid a browser quirk that’s caught me out a few times. When calculating transforms and transform-origin, some browsers use the element’s bounding box as the reference box and others use the SVG viewbox.

If you set the value to fill-box the objects bounding box is used as the reference box.

And if you set the value to view-box the nearest SVG viewbox is used as the reference box.

You can see what happens to the center of rotation when we change it here:

See the Pen Rocket – CSS motion path – transform-box by Cassie Evans (@cassie-codes) on CodePen.default

GreenSock Animation Platform (GSAP)

While we wait for the CSS solution to be more widely implemented we’re in a bit of a motion path limbo. Thankfully there’s some JavaScript animation libraries that are bridging this gap.

I usually use GreenSock for SVG animation for a few reasons.

There are some cross browser quirks with SVG, especially with how transforms are handled. The folks at GreenSock go above and beyond to handle these inconsistencies.

Animation can also be a bit fiddly, especially when it comes to fine-tuning timings and chaining different animations together. GreenSock gives you a lot of control and makes creating complex animations fun.

They also provide some plugins that are great for SVG animation like DrawSVG, MorphSVG and MotionPathPlugin.

They’re all free to experiment with on Codepen, but some of the plugins are behind a membership fee. MotionPathPlugin is one of the free ones, and part of the new GSAP 3 release.

MotionPathPlugin gives you the ability to turn an SVG path into a motion path, or specify your own path manually. You can then animate SVG or DOM elements along that path, even if those elements are in a completely different coordinate space.

Here’s a demo with the necessary libraries added to start you off.

In order to use a plugin we have to register it, like this:

gsap.registerPlugin(MotionPathPlugin);

Then we can start animating. This is what a tween using the simplified GSAP 3 syntax looks like:

gsap.to(".rocket", {
	motionPath: ...
	duration: 5,
});

The name ‘tween’ comes from the world of hand-drawn animation, too.

Tweening is the process of generating intermediate frames between two images to give the appearance that the first image evolves smoothly into the second image.

That’s pretty much what a GSAP tween does. You feed in the element you want to animate, the duration, and the properties you want to target and the tween will figure out the in-between states.

The motionPath attribute can be used shorthand, and passed a path:

gsap.to(".rocket", {
	motionPath: "#path",
	duration: 5,
});

Or, if we want more control over the settings we can pass it an object of options:

gsap.to(".rocket", {
	motionPath: {
		path: "#path",
		align: "#path",
		autoRotate: true,
	},
	duration: 5,
});

See the Pen Rocket – GSAP motion path by Cassie Evans (@cassie-codes) on CodePen.default

Here are some of the properties we can control.

path

This defines the motion path we’re animating along, we can reference a path that exists in the document by using a selector,

motionPath: {
	path: "#path",
}

a string that contains SVG path data,

motionPath: {
	path: 'M125.7 655a9.4 9.4...',
}

an object containing an array of x and y co-ordinates to move between,

motionPath: {
	path: [{x: 100, y: 100}, {x: 300, y: 20}]
}

or a variable referring to one of these options:

const myPath = 'M125.7 655a9.4 9.4...'

motionPath: {
	path: myPath,
}

align

We can use this to align the element to the path, or other elements in the document by passing in a selector:

motionPath: {
	path: "#path",
	align: "#path"
}

We can also align the element to itself if we want the animation to start from the element’s current position.

motionPath: {
	path: "#path",
	align: "self"
}

In the next demo, the purple rocket is aligned to self and the green rocket is aligned to the path.

align: “self” is like moving the path to the element, rather than the element to the path.

See the Pen Rocket – GSAP motion path – align by Cassie Evans (@cassie-codes) on CodePen.default

By default, the element’s top left corner will be the center of rotation and alignment. In order to align the element accurately on the path you’ll need to set the element’s center of rotation, like this:

gsap.set(".rocket", { 
	xPercent: -50,    
	yPercent: -50,    
	transformOrigin: "50% 50%"
});

autoRotate

This is how we get our element to rotate along with the curvature of the path:

motionPath: {
	path: "#path",
	align: "#path"
	autoRotate: true,
}

We can also provide a number value. This will rotate along with the path, but maintain that angle relative to the path.

motionPath: {
	path: "#path",
	align: "#path"
	autoRotate: 90,
}

start & end

These properties let us define where on the path the motion should begin and end.

By default, it starts at 0 and ends at 1, but we can provide any decimal number:

motionPath: {
	path: "#path",
	align: "#path"
	autoRotate: true,
	start: 0.25,
	end: 0.75,
}

If you want the element to go backwards along the path, you can provide negative numbers.

See the Pen Rocket – GSAP motion path – align by Cassie Evans (@cassie-codes) on CodePen.default

immediateRender

If your element is starting off at a different position in the document and you want it to align with the path you might notice a jump as it moves from its position to the path.

See the Pen Rocket – GSAP motion path – align by Cassie Evans (@cassie-codes) on CodePen.default

You can fix force it to render immediately upon instantiation by adding immediateRender:true to the tween.

// animate the rocket along the path
gsap.to(".rocket", {
    motionPath: {
        path: "#path",
        align: "#path",
        autoRotate: true,
    },
    duration: 5,
    ease: "power1.inOut",
    immediateRender: true,
});

MotionPathHelper

Another super cool feature of the GSAP 3 release is the MotionPathHelper.

It enables you to edit paths directly in the browser! I found this really helpful, as I’m always going back and forth between the browser and my graphics editor.

Give it a go in the demo below. When you’re done, click “copy motion path” to copy the SVG path data to your clipboard. Paste the new path data into the d=”” attribute in the SVG code to update your path.

There are instructions on how to edit the path in the GSAP docs.

See the Pen Rocket – GSAP motion path – helper by Cassie Evans (@cassie-codes) on CodePen.default

GreenSock is a ton of fun to play around with!

There are a bunch of other features and plugins that when paired with motion path animation can be used to create really cool effects.

In this demo, DrawSVG is progressively showing the text path as some staggered elements animate along the path using MotionPathPlugin:

See the Pen Squiggle text animation by Cassie Evans (@cassie-codes) on CodePen.default

If you’ve had fun with these examples and want to explore GreenSock some more, Christina Gorton has written The New Features of GSAP 3 providing a practical overview.

GreenSock also have a great getting started guide.

Happy animating!

Motion Paths – Past, Present and Future was written by Cassie Evans and published on Codrops.

The New Features of GSAP 3

In this article we will explore many of the new features available from GSAP 3. The GreenSock animation library is a JavaScript library many front-end developers turn to because it can be easy to get started and you can create powerful animations with a lot of control. Now with GSAP 3 getting started with GreenSock is even easier.

Some of the new features we will cover in this article are:

  • GreenSock’s smaller file size
  • A Simplified API which offers a newer syntax
  • Defaults in timelines
  • Easier to use with build tools and bundlers
  • Advanced stagger everywhere!
  • Keyframes
  • MotionPath and MotionPath plugin
  • use of Relative “>” and “<” position prefix in place of labels in Timelines
  • The new “effects” extensibility
  • Utility methods

…and more!

GreenSock’s smaller file size

First and foremost the GreenSock library is now even smaller. It still packs all the amazing features I love, plus more (50+ more to be exact). But it is now about half the size! We will see some of the reasons below like the new simplified API but at its core GSAP was completely rebuilt as modern ES modules.

A Simplified API

With the new version of GreenSock we no longer have to decide whether we want to use TweenMax, TweenLite, TimelineMax, or TimelineLite. Now, everything is in a single simplified API so instead of code that looks like this:

TweenMax.to('.box', 1, {
  scale: 0.5,
  y: 20,
  ease: Elastic.easeOut.config( 1, 0.3)
})

We can write this instead:

gsap.to(".box1",{
  duration: 1,
  scale: 0.5,
  y: 20     // or you can now write translateY: 20,
  ease: "elastic(1, 0.3)",
});

Creating Timelines is easier too. Instead of using new TimelineMax() or new TimelineLite() to create a timeline, you now just use gsap.timeline() (simpler for chaining).

Here is an example of the first syntax change. Note that the old syntax still works in GSAP 3 for backward compatibility. According to GreenSock, most legacy code still works great.

See the Pen GreenSock New vs Old syntax by Christina Gorton (@cgorton) on CodePen.dark

Duration

Previously, the animation’s duration was defined as its own parameter directly after the target element. Like this:

TweenMax.to('.box', 1, {})

With the new version, duration is defined in the same vars object as the rest of the properties you animate and therefore is more explicit.

gsap.to(".box",{
  duration: 2,
});

This adds several benefits such as improved readability. After working with and teaching GSAP for a while now, I agree that having an explicit duration property is helpful for anyone new to GreenSock and those of us who are more experienced. This isn’t the only thing the new API improves though. The other benefits will become more obvious when we look at defaults in timelines and the new Keyframes.

Defaults in timelines

This new feature of GSAP is really wonderful for anyone who creates longer animations with gsap.timeline(). In the past when I would create long animations I would have to add the same properties like ease, duration, and more to each element I was animating in a timeline. Now with defaults I can define default properties that will be used for all elements that are animated unless I specify otherwise. This can greatly decrease the amount of code you are writing for each timeline animation.

Let’s take a look at an example:

This Pen shows a couple of the new features in GSAP 3 but for now we will focus on the defaults property.

See the Pen Quidditch motionPath by Christina Gorton (@cgorton) on CodePen.dark

I use defaults in a few places in this pen but one timeline in particular shows off its power. At the beginning of this timeline I set defaults for the duration, ease, yoyo, repeat, and the autoAlpha property. Now instead of writing the same properties for each tween I can write it one time.

const moving = () => {
  let tl = new gsap.timeline({ 
    defaults: { 
      duration: .02,  
      ease: "back(1.4)", 
      yoyo: true, 
      repeat: 1, 
      autoAlpha: 1 
    }
  })
  tl.to('.wing1',{})
    .to('.wing2',{})
    .to('.wing3',{})
  
  return tl;
}

Without the defaults my code for this timeline would look like this:

const moving = () => {
  let tl = gsap.timeline()
  
  tl.to('.wing1',{
    duration: .02,  
    ease: "back(1.4)", 
    yoyo: true, 
    repeat: 1, 
    autoAlpha: 1
  })
  .to('.wing2',{
    duration: .02,  
    ease: "back(1.4)", 
    yoyo: true, 
    repeat: 1, 
    autoAlpha: 1
  })
  .to('.wing3',{
    duration: .02,  
    ease: "back(1.4)", 
    yoyo: true, 
    repeat: 1, 
    autoAlpha: 1
  })

  return tl;
}

That is around a 10 line difference in code!

Use of Relative > and < position prefix in place of labels in Timelines

This is another cool feature to help with your timeline animations. Typically when creating a timeline I create labels that I then use to add delays or set the position of my Tweens.

As an example I would use tl.add() to add a label then add it to my tween along with the amount of delay I want to use relative to that label.

The way I previously used labels would look something like this:

gsap.timeline()
  .add("s")
  .to(“.box1", { ... }, "s")
  .to(“.box2", { ... }, "s")
  .to(“.box3", { ... }, "s+=0.8")
  .to(“.box4", { ... }, "s+=0.8”);

See an example here.

With > and < you no longer need to add a label.

From the GreenSock docs:

"Think of them like pointers - "<" points to the start, ">" points to the end (of the most recently-added animation)."

  • "<" references the most recently-added animation's START time
  • ">" references the most recently-added animation's END time

So now a timeline could look more like this:

gsap.timeline()
  .to(“.box1", { ... })
  .to(“.box2", { ... }, "<")
  .to(“.box3", { ... }, "<0.8")
  .to(“.box4", { ... }, "<”);

And you can offset things with numbers like I do in this example:

See the Pen MotionPath GreenSock v3 by Christina Gorton (@cgorton) on CodePen.dark

Stagger all the things

Previously in GSAP to stagger animations you had to define it at the beginning of a tween with either a staggerTo(), staggerFrom(), or staggerFromTo() method. In GSAP 3 this is no longer the case. You can simply define your stagger in the vars object like this:

tl.to(".needle",{
  scale: 1,
  delay:0.5,
  stagger: 0.5 //simple stagger of 0.5 seconds
},"start+=1")

...or for a more advanced stagger you can add extra properties like this:

tl.to(".needle",{
  scale: 1,
  delay:0.5,
  stagger: {
    amount: 0.5, //  the total amount of time (in seconds) that gets split up among all the staggers. 
    from: "center" // the position in the array from which the stagger will emanate
  }
},"start+=1")

This animation uses staggers in several places. like the needles. Check out all the staggers in this pen:

See the Pen Cute Cactus stagger by Christina Gorton (@cgorton) on CodePen.dark

Easier to use with build tools and bundlers

When I have worked on Vue or React projects in the past working with GreenSock could be a little bit tricky depending on the features I wanted to use.

For example in this Codesandbox I had to import in TweenMax, TimelineMax and any ease that I wanted to use.

import { TweenMax, TimelineMax, Elastic, Back} from "gsap";

Now with GSAP 3 my import looks like this:

import gsap from "gsap";

You no longer have to add named imports for each feature since they are now in one simplified API. You may still need to import extra plugins for special animation features like morphing, scrollTo, motion paths, etc.

Keyframes

If you have ever worked with CSS animations then keyframes will be familiar to you.

So what are keyframes for in GreenSock?

In the past if you wanted to animate the same set of targets to different states sequentially (like "move over, then up, then spin"), you would need to create a new tween for each part of the sequence. The new keyframes feature lets us do that in one Tween!

With This property you can pass an array of keyframes in the same vars objects where you typically define properties to animate and the animations will be nicely sequenced. You can also add delays that will either add gaps (positive delay) or overlaps (negative delay).

Check out this example to see the keyframes syntax and the use of delays to overlap and add gaps in the animation.

See the Pen GreenSock Keyframes by Christina Gorton (@cgorton) on CodePen.dark

MotionPath and MotionPath helper plugin

One of the features I am most excited about is MotionPathPlugin and the MotionPathHelper. In the past I used MorphSVGPlugin.pathDataToBezier to animate objects along a path. Here is an example of that plugin:

See the Pen MorphSVGPlugin.pathDataToBezier with StaggerTo and Timeline by Christina Gorton (@cgorton) on CodePen.dark

But the MotionPathPlugin makes it even easier to animate objects along a path. You can create a path for your elements in two ways:

  • With an SVG path you create
  • Or with manual points you define in your JavaScript

The previous Quidditch pen I shared uses MotionPathPlugin in several places. First you need to register it like this:

//register the plugin
gsap.registerPlugin(MotionPathPlugin);

Note: the MotionPathHelper plugin is a premium feature of GreenSock and is available to Club GreenSock members but you can try it out for free on CodePen.

I used an SVG editor to create the paths in the Quidditch animation and then I was able to tweak them directly in the browser with the MotionPathHelper! The code needed to add the MotionPathHelper is this

MotionPathHelper.create(element)

Screen Shot 2019-11-13 at 4.52.09 PM

I then clicked "COPY MOTION PATH" and saved the results in variables that get passed to my animation(s).

Paths created with the MotionPathPlugin helper

const path = "M-493.14983,-113.51116 C-380.07417,-87.16916 -266.9985,-60.82716 -153.92283,-34.48516 -12.11783,-77.91982 129.68717,-121.35449 271.49217,-164.78916 203.45853,-70.96417 186.21594,-72.24109 90.84294,-69.64709   ",
      path2 ="M86.19294,-70.86509 C64.53494,-36.48609 45.53694,-13.87709 -8.66106,-8.17509 -23.66506,-40.23009 -30.84506,-44.94009 -30.21406,-88.73909 6.79594,-123.26109 54.23713,-91.33418 89.94877,-68.52617 83.65113,-3.48218 111.21194,-17.94209 114.05694,18.45191 164.08394,33.81091 172.43213,34.87082 217.26913,22.87582 220.68213,-118.72918 95.09713,-364.56718 98.52813,-506.18118  ",
      path3 = "M-82.69499,-40.08529 C-7.94199,18.80104 66.81101,77.68738 141.56401,136.57371 238.08201,95.81004 334.60001,55.04638 431.11801,14.28271 ",
      path4 = "M126.51311,118.06986 C29.76678,41.59186 -66.97956,-34.88614 -163.72589,-111.36414 -250.07922,-59.10714 -336.43256,-6.85014 -422.78589,45.40686 ";

Example of a path passed in to animation

const hover = (rider, path) => {
  let tl = new gsap.timeline();
  tl.to(rider, {
    duration: 1,
    ease: "rider",
    motionPath:{
      path: path,
    }
  })
  return tl
}

In this timeline I set up arguments for the rider and the path so I could make it reusable. I add which rider and which path I want the rider to follow in my master timeline.

.add(hover("#cho", path3),'start+=0.1')
.add(hover("#harry", path4),'start+=0.1')

If you want to see the paths and play around with the helper plugin you can uncomment the code at the bottom of the JavaScript file in this pen:

See the Pen Quidditch motionPath by Christina Gorton (@cgorton) on CodePen.dark

Or, in this pen you can check out the path the wand is animating on:

See the Pen MotionPath GreenSock v3 by Christina Gorton (@cgorton) on CodePen.dark

Effects

According the the GreenSock Docs:

Effects make it easy for anyone to author custom animation code wrapped in a function (which accepts targets and a config object) and then associate it with a specific name so that it can be called anytime with new targets and configurations

So if you create and register an effect you reuse it throughout your codebase.

In this example I created a simple effect that makes the target "grow". I create the effect once and can now apply it to any element I want to animate. In this case I apply it to all the elements with the class ".box"

See the Pen GreenSock Effects by Christina Gorton (@cgorton) on CodePen.dark

Utility methods

Lastly, I'll cover the utility methods which I have yet to explore extensively but they are touted as a way to help save you time and accomplish various tasks that are common with animation.

For example, you can feed any two similarly-typed values (numbers, colors, complex strings, arrays, even multi-property objects) into the gsap.utils.interpolate() method along with a progress value between 0 and 1 (where 0.5 is halfway) and it'll return the interpolated value accordingly. Or select a random() value within an array or within a specific range, optionally snapping to whatever increment you want.

Most of the 15 utility methods that can be used separately, combined, or plugged directly into animations. Check out the docs for details.

Below I set up one simple example using the distribute() utility which:

Distributes an amount across the elements in an array according to various configuration options. Internally, it’s what advanced staggers use, but you can apply it for any value. It essentially assigns values based on the element’s position in the array (or in a grid)

See the Pen GreenSock Utility Methods by Christina Gorton (@cgorton) on CodePen.dark

For an even more impressive example check out Craig Roblewsky's pen that uses the distribute() and wrap() utility methods along with several other GSAP 3 features like MotionPathPlugin:

See the Pen MotionPath Distribute GSAP 3.0 by Craig Roblewsky (@PointC) on CodePen.dark

That wraps up the features we wanted to cover in this article. For the full list of changes and features check out this page and the GreenSock docs. If you'd like to know what old v2 code isn't compatible with v3, see GreenSock's list. But there's not much as GSAP 3 is surprisingly backward-compatible given all the improvements and changes.

References

All of the Pens from this article can be found in this collection.

For more examples check out GreenSock's Showcase and Featured GSAP 3 Pens collection.

The New Features of GSAP 3 was written by Christina Gorton and published on Codrops.