
No Comments Yet
Be the first to share your thoughts and start the conversation.

Be the first to share your thoughts and start the conversation.
Most animations are content to arrive quietly.
But sometimes, your UI needs to make an entrance with a little flair, a little overshoot, a little “ta-da”.
That’s where back easing comes in.
Back easing adds a bit of rebound to the motion. It feels like the animated element overreaches its target, then gently corrects itself.
This means that instead of going from Point A to Point B in a straight line or simple curve, it goes a little too far (forward or backward) and then comes back and settles into place.
In GSAP, it comes in three variations:
ease: "back.in" // pulls backward first, then moves forward
ease: "back.out" // moves past the destination, then comes back
ease: "back.inOut" // combines both: pulls back, overshoots, settlesYou can also customize how much it should overshoot,
ease: "back.out(2.5)" // higher number = more dramatic bounceDon’t just read. Try it out to see how back easing works with different variations right here.
You can test these easings on a circle too. Feel free to play around these to understand how each variation works.
You can use back easing when something is entering with flair (modals, cards, tooltips), snapping to position (like tabs or buttons reacting), or reacting to an interaction (press, hover, focus).
This easing is expressive. It’s great when you want your animation to feel , without going over the top like a bounce or elasticity.
Your challenge is to build a tabbed Navigation system inspired by Apple Music or Notion. The system should have an “active tab” indicator below it that moves when a different tab is clicked.
I hope you got a real sense of what back easing brings to the table. It’s a different personality motion that makes things feel alive without feeling too much.
Up next, you’ll push motion further to make things land with more energy.
00:00:32 Well, first things first, in this case, we'll have to select a couple of elements.
00:00:37 There is a tab, an indicator, and a tab row.
00:00:43 So since we're working with Plane.js, let's go ahead and grab all of these by saying const tabs is equal to document.querySelectorAll.
00:00:54 And then we can just target a dot tab right here.
00:00:57 We can duplicate this two more times.
00:01:00 For the second two, we can just use a regular query selector and we can call it indicator and target the dot indicator class name.
00:01:10 And the last one will be a tab row where we can query select a tab dash row.
00:01:16 Perfect.
00:01:17 So now we grabbed all the tab buttons, the moving underline and the container that holds all the tabs.
00:01:24 Now, we have to create a function called UpdateIndicator.
00:01:28 So I'll say function UpdateIndicator.
00:01:32 That looks like this.
00:01:34 Of course, if you want to, you're totally free to use the ES6 version of this, which would look something like this with an arrow function in mind.
00:01:42 Both of these versions work just fine.
00:01:45 Now within this update indicator function, we first have to get access to the bounds of specific elements.
00:01:53 So for example, we can get access to the bounds of the tab by saying tab bounds is equal to, and now what are we getting the bounds of?
00:02:03 Well, it's going to be the target element that we're going to pass as the prop into the update indicator function.
00:02:09 So that's going to be target dot get bounding client rect, as in rectangle.
00:02:17 And we can do the same thing for the row bounds by saying const row bounds, which is going to be the tab row dot get bounding client rect.
00:02:29 What this is doing is figuring out where the clicked tab is inside the row.
00:02:35 So let's get access to its width by saying tab bounds dot width.
00:02:41 And let's also get access to its offset by how much we want to move it, which is going to be equal to tab bounds dot left.
00:02:50 So the element on the left.
00:02:52 minus rowBounds.left.
00:02:55 And then GSAP will allow us to move the indicator to match the tab's position and width by using GSAP.to method on the indicator itself.
00:03:06 And then we can move the X position by the offset that we have calculated right here.
00:03:13 We can set its width to be equal to the width that we have also calculated right here.
00:03:18 You can choose a duration of something like 0.4. And then finally, you can choose the ease which you want to apply.
00:03:25 In this case, we'll use the back.out 1.7 ease, which I found it works very well with the tab layout.
00:03:32 So once again, the X position will shift the indicator horizontally.
00:03:37 Width will match the tab's size throughout a duration of 0.4 seconds with this back easing.
00:03:44 So now let's implement the actual tab bar logic.
00:03:48 We can do that below the indicator by saying tabs.forEachTab.
00:03:55 We can apply an event listener by saying tab.addEventListener.
00:04:01 of click.
00:04:03 And then we can define a callback function that gets executed on the click.
00:04:07 Once we click on each one of these indicators, we want to remove all other active classes from the other ones by saying tabs.forEach.t just run the t.classList.remove
00:04:23 and remove the active class from all of them because we want to only add it to the currently selected one.
00:04:29 So I'll say tab.classList.add and I'll make it active.
00:04:35 Finally, we want to call this updateIndicator function so that we can actually animate it.
00:04:40 So I'll say updateIndicator and pass in the tab that we want to add the indicator for.
00:04:45 And let's actually go ahead and call this update indicator once so it's already positioned on the pre-selected tab.
00:04:53 We can do that by saying update indicator, get the document.querySelector of the current active tab, like this.
00:05:03 So now if you save this and reload, you can see that it still remains on the first selected tab.
00:05:09 And now, if you navigate over to features, notice how the indicator moves from left to right or back.
00:05:17 It can even move all the way here to the end and notice how quickly it spins because the duration still takes 0.4 seconds no matter whether it moves from
00:05:28 here to here, like one spot, or it jumps over three of these additional tabs and goes to the first one.
00:05:35 So why exactly did I choose the back out ease in this case?
00:05:40 Well, back out is an easing function that makes the animation go slightly past the target value and then come back, like a bounce or a recoil.
00:05:50 So if I click support, notice how it jumps out.
00:05:53 Same thing, take a look at the left corner, it jumps out.
00:05:57 So, the back motion will actually overshoot the target before settling, The Out is the effect that happens at the end of the animation,
00:06:06 which means that it starts fast and then ends with a bounce, and then 1.7 is the overshoot amount.
00:06:13 The higher it is, the more dramatic the bounce.
00:06:16 So if I set it to something like 10, just take a look at this.
00:06:20 It jumps out so much, it's pretty crazy.
00:06:25 So we want to keep it something reasonable, like 1.7. So why is it useful for this specific case?
00:06:31 Well, because it makes it feel snappy and organic.
00:06:34 The overshoot makes the UI feel alive, and it avoids stiff and robotic motion.
00:06:39 Of course, you can switch it to my favorite, like power1.inout, which will still be smooth, but it'll have no bounce, which is much less tactile.
00:06:50 Yeah, you can see the difference, right?
00:06:52 It kind of feels a bit slow and sluggish.
00:06:56 You could also try the bounce and take a look.
00:07:00 This one, yeah, it bounces, but it bounces in place and it looks a bit unnatural.
00:07:07 So this back out is definitely the best easing function to implement for this indicator animation.
00:07:14 Great job.