The Macro World of Micro Interactions

What good interaction animation is actually made of.

My first ever animation that I sold to a client was very boring. One keyframe at the beginning, one keyframe at the end. That was the whole thing.

It felt like an automatic PowerPoint presentation. Slow, and with nothing in it that had anything to do with the brand or the style of the product.

I sent it to the client anyway, thinking this was top notch work. Looking back at it now, it was very jugaad and honestly trash. Maybe I should apologise to the client? Idk.

This whole page is what I should have known back then. I made the mistakes and learned all of it the hard way. You don't have to.

A quick word about the numbers on this page. They are real numbers from real products. But they change the moment your style or the mood of your animation changes. A calm meditation app and a fast trading screen will need completely different values, and both can be right.

So don't copy the numbers. Copy the logic and the thinking behind them. That way you can work out your own numbers for your own product, which is the actual skill.

Let's look at one animation across its whole life. From the beginning when it starts, to the zillionth time it plays, when it stops being something you enjoy and becomes just another element on the screen.

Media slot 1
Hero. A single UI animation shown deconstructed, exploded-view style: a button press broken into its phases laid out horizontally on a timeline (idle, pressed, transition frames, end state), each frame slightly separated, minimal flat design, muted palette, loops slowly. Build in After Effects from own files.
Stage 0

The trigger

Here is something we have all done. We add only one interaction to a button. The pressed state darkens, it changes into a loader, and then it changes into "Done" or a tick.

In reality this needs to be two animations, not one.

From an implementation point of view: the moment the user presses the button, the pressed state and the loader start. They do not wait for anything. Later, once the process finishes and the backend says yes, all done, we change it into the success state.

One animation belongs to the press. The other belongs to the result. They have different owners and different timings, so they should be built separately.

Let's learn about triggers now.

There are two kinds, and they need completely different treatment.

  1. Fire and forget. A simple action like a tap or a click. You do it once and it's over. The animation that follows runs on its own timing.
  2. Steered. Actions where your finger or your mouse stays involved for longer. Drag, swipe, draw, pinch, pull to refresh. The animation follows your hand for as long as you keep going.

The second kind is much harder to get right, because of lag.

Lag is simply the time between you doing something and you seeing the result. Gamers care about this more than anyone. From the moment they click the mouse to the moment the gun actually fires on screen, every millisecond is a millisecond in which they can be shot first. That is why they spend money on monitors and mice that most people would never think about.

Interfaces have the same problem in a smaller form. In lab tests, people start noticing lag while dragging at around 11 milliseconds, because they can see a gap opening up between their finger and the thing they think they are holding. For tapping, anything under about 24 milliseconds is invisible to us, and the point where people reliably notice sits closer to 69 milliseconds (Jota, Ng, Dietz and Wigdor, CHI 2013). Dragging is roughly six times more sensitive than tapping, so it deserves that much more care.

The animations for these two kinds of trigger need to follow different patterns.

For tap and click, the animation should stay where it is. The user is already looking at that spot, so they will see whatever happens there. Do not move the button somewhere else. Let it change in place, and let the user watch it.

For steered actions, the element has to move with the movement. Properly. If it moves less than the finger does, it reads as though the element does not want to move, and the whole thing feels sticky. While it is moving, changing its colour or its content is too much visual information for anyone to follow. Keep the element as it is, move it with the hand, and if you need to show something changing, opacity is usually enough.

If you want the long version of the steered kind, Apple's Designing Fluid Interfaces is still the best hour recorded on it. Dan Saffer's Microinteractions is where all these words come from.

Media slot 2
Broken versus fixed, side by side, same button. Left: everything is one animation wired to the server reply, so on a slow connection nothing at all happens for half a second and then the press, loader and success arrive together. Right: the press and loader fire on touch, the success arrives on its own later. Same UI both sides, simple mobile form, neutral colours. Custom-built. Do not source a hardware latency demo, the point is what the animation is wired to.

Try it yourself

Drag the box around with various values selected and see how it affects your experience.

Stage 1

The delay

Now here is the second part of any interaction animation. Let the user actually see it.

You have seen this happen. A list refreshes, the loader appears and disappears almost instantly, and the content is just there. I know it reads as fast, and technically nothing was wrong. But it feels like a waste of an animation. Why did we even load the script that draws that loader, if nobody was going to see it? Every byte counts, doesn't it.

So instead, we add a delay. Something small, around half a second. And we use an animation that itself communicates speed, like a skeleton loader. The content then loads into the same place the skeleton was sitting. If all of that happens in under half a second, the page still feels fast, and it also feels a bit premium.

In practice this comes down to two settings.

  • Don't show the loader until the wait crosses roughly 400 milliseconds. Most requests finish before that, so you skip the flash completely.
  • Once the loader is visible, keep it there for roughly 500 milliseconds, even if the data arrives sooner, so that it actually gets seen.

Many dev teams already have these delays baked into their tooling. Oracle APEX, for example, ships it by default. Treat these numbers as a good starting point and not as the source of truth. None of them were arrived at by putting the animation in front of a user group and measuring what happened. They are convention, and convention is usually sensible, but it is not proof.

There are two more things worth knowing here.

The first is about the famous response time limits. A tenth of a second feels instant. One second keeps you in your flow. Ten seconds is about as long as anyone will keep paying attention. These are real research, from Robert B. Miller in 1968 and made popular by Nielsen.

But look at what those numbers actually measure. They measure how quickly the system answers you. They say nothing about how long your animation should run for. People use the one second figure to defend a one second transition all the time, and that is not what the research says at all.

The second is the skeleton versus spinner argument, which is nowhere near as settled as design Twitter thinks. The Viget study put skeletons last on every single thing they measured. Mejtoft and co found the opposite. The Nokia and VTT study found that what really changed how fast things felt was simply getting the real content in front of the eye sooner.

So pick one, stop arguing about it in design review, and go make the data arrive faster. Baaki sab detail hai.

Media slot 3
A short recording of the loader flash: a list refreshes, a spinner appears for a split second and vanishes before you can register it, content pops in. Real world feel, any common app pattern like mail or a feed. Custom-built, or captured from the demo component below.

Try it yourself

Load the same data both ways at three different server speeds, and watch which side looks broken.

Stage 2

The anticipation

Imagine you are waiting for something good to happen. You want it to happen faster. You are ordering food, you are at the checkout, and all you want is for the payment to go through so the food starts coming. A quick animation helps you here. A slow one just stands in your way.

Now imagine the opposite. The order is placed, the payment worked, and the app plays a small celebration. Here you don't mind waiting a second. Nothing is being held up. You are just being told something nice.

Same app, same day, two completely different speeds. This is the stage where that difference shows up.

For years I animated a loader, a button and a screen transition in exactly the same way. Same curve, same slow start on all three. Ek hi recipe, teen alag dishes.

The button suffered the most. I had given it a tiny wind up, a few frames where it pulls back slightly before it responds. On a screen transition that looks lovely. On a button it makes the button feel like it is thinking about whether to obey you. A button that hesitates feels broken even when it is working perfectly.

That wind up has a name. Anticipation. It is the small backwards movement before a forwards one. A person crouches before they jump. A drawer pulls back a little before it slides open. Cartoon animators have used it forever, and Chang and Ungar brought it into interfaces in 1993 with a simple argument: give people a hint about where this is going, so they can guess the ending before it arrives.

The useful question is how much of it you can afford, and the answer depends entirely on how often the thing happens.

A button gets none. You pressed it, it responds, finished. The whole animation lives in 100 to 150 milliseconds, because the button barely moves and its only job is to tell you it heard you.

A celebration gets plenty. A payment clearing, an onboarding finishing, a first order placed. It can spend 80 to 100 milliseconds on a wind up and run for a full second afterwards. Not because it matters more, but because it happens rarely, and because it is carrying a feeling rather than information.

I should be straight with you about the evidence here. Almost none of this has been tested properly for interfaces. There is no study that says when a wind up helps or how long it should be. This section is my judgement and the judgement of a lot of people I have worked with, and I would rather say that out loud than dress it up as science.

IBM Carbon is the only large design system that names this split openly. It calls them productive and expressive motion. Its rules for productive motion are refreshingly rude: no bounce, no stretch, no drama. That is correct.

Media slot 4
Two contrasting examples. First: a task focused productive animation, for example a dropdown or a table row expanding, fast and with no flourish, enterprise clean visual style. Second: an expressive celebration animation, for example a confetti or tick burst success moment from a consumer app, playful and willing to take its time. Source both from Dribbble with credit; search "dropdown micro interaction minimal" and "success celebration animation confetti". The pairing is the point: same craft, opposite spends.
Stage 3

The body

Now we get to the part in the middle, where the thing is actually moving. This is where my first animation went wrong, and it is the most common mistake there is.

Everything was linear. The panel slid in at one constant speed, hit its position, and stopped dead. It looks like a machine part sliding along a rail, and most people can tell something is off without being able to say what.

Here is why. Nothing you have ever picked up moves like that. A bus pulling away from a stop starts slowly and builds up. A cricket ball slows down before it stops rolling. Everything real has weight, so everything real speeds up and slows down. Your eye learned this before you could read, and linear movement feels robotic and unnatural even without you consciously noticing anything.

The fix takes about ten seconds to apply.

  • Something arriving on screen should be fast at the start and slow at the end. This is called ease out.
  • Something leaving the screen should be slow at the start and fast at the end. This is called ease in.

That covers the large majority of what you will ever build.

The thing controlling this is called a timing function, and it is simpler than it sounds. It is two control points on a curve. One decides how the movement starts, the other decides how it ends. That is the whole vocabulary, and it is enough to give the same 200 milliseconds a dozen different personalities.

Try it yourself

Same distance, same duration, different curve. Drag the control points around, or switch to a spring, and turn on the ghost to compare against linear.

Linear does have real jobs. A scrolling marquee, a spinner going round and round, anything with no beginning and no end. Everywhere else, if you picked the curve without thinking, your product has a personality that nobody chose on purpose.

Then there is the question of how long it should run.

  • A small thing moving a short distance, like a dropdown opening or a row expanding, wants about 150 to 200 milliseconds.
  • A full screen changing to another full screen wants about 300 to 400 milliseconds.

The difference between those two is distance, not importance. It is the same speed, just a longer journey. If you remember one thing from this section, remember that: pick your duration from how far the thing has to travel.

Something that genuinely surprised me while putting this page together is that the big platforms do not just use different numbers. They disagree about the whole idea.

  • Material 3 is happy to run animations up to a full second, with soft curves.
  • Fluent 2 caps out at roughly half of that, and uses sharp curves that hit full speed straight away.
  • Apple publishes no durations at all. Their session on springs tells you to stop thinking in durations completely and tune a spring until it feels right, because a spring starts from wherever the object currently is and however fast it is currently going. That is what lets you interrupt it cleanly.

Three of the biggest design teams in the world, three answers that contradict each other. Take that as your permission to stop hunting for the one correct table of numbers.

One last thing about this stage. The moment more than one element moves at the same time, you are no longer animating, you are choreographing.

People can follow about four or five moving things at once before their attention gives up (Pylyshyn and Storm, 1988). So stagger them. Put 30 to 50 milliseconds between each item, which is enough for the eye to read it as a sequence instead of a swarm. Below 30 they look simultaneous, so you have gained nothing. Above 50 and the last card in a long list is still arriving after the reader has moved on.

Twelve cards entering together is not choreography, it is khichdi.

Media slot 5
A list entry animation done well: cards or rows entering with a subtle stagger, each element clearly sequenced, modern dashboard or feed UI. Source from Dribbble with credit; search "staggered list animation UI" or "cards entrance motion". Prefer an example with restraint over a showreel piece.

Try it yourself

Bring twelve tiles in three different ways and see which one you can actually follow.

Stage 4

The arrival

Open a detail screen in a badly built app. The card fades out, a blank screen fades in, and for a moment you have no idea what you are looking at. It is only 300 milliseconds, and it still feels slow.

Now open the App Store and tap a card. It grows into the full page, and the title stays on the screen the entire time. That one takes longer, and it feels quicker.

So here is the thing I believe, and I want to be honest that it is a belief and not a finding. What matters is when the reader can read the ending, not when the movement stops. A slow transition you can understand early beats a fast one that is still confusing when it lands.

I went looking for a study that isolates exactly this and I could not find one, so take it as mine.

The closest evidence is Heer and Robertson. They found that staged transitions, where one thing happens and then the next thing happens, measurably helped people keep track of objects through a change. Staging works because the eye gets to read the destination while the movement is still going on. Their rule is worth writing down: as long as needed, but no longer.

In practice this means you should keep something alive across the transition. The title, the image, the outline of the card. One element that does not die and get born again is worth more than any amount of curve tuning.

Media slot 6
A screen transition where the destination content is readable well before the motion settles, for example a shared element transition where the tapped card grows into the detail view and its title never disappears. iOS App Store card to detail is the reference; record the real interaction, or record Motion's live recreation at https://motion.dev/examples/js-app-store-layout with credit.
Stage 5

The settle

Watch a good animation finish. It does not stop. It lands.

The thing that makes it land is a small overshoot. The element goes slightly past where it is supposed to end up, and then comes back. One setting controls how much of that you get, and it is called damping.

Think of a door closer, the metal arm at the top of an office door. Tighten it and the door closes firmly with no bounce at all. Loosen it and the door swings past, comes back, and takes a moment to settle. Damping is that adjustment.

  • Damping of about 1.0 means it arrives cleanly with no bounce. This is your default for anything useful and everyday: menus, panels, form controls.
  • Around 0.6 to 0.8 it goes slightly past and comes back once. This reads as friendly, and it suits celebrations and consumer moments.
  • Below about 0.5 it wobbles several times, and wobble stops being charming very quickly.

Where exactly it stops being charming, nobody has published. The most useful thinking on it comes from game design rather than from interface research. Steve Swink's Game Feel treats overshoot as something you deliberately engineer for satisfaction, with a standing warning that thoda zyada juice drowns the message you were trying to send.

The platforms split here too, along brand lines. iOS bounces, and that rubber band feel is basically Apple's signature. Carbon bans bounce completely for productive work. Both are right for the products they were written for, which is this entire page compressed into one sentence.

There is one more thing here, and it explains a bug you will definitely hit at some point.

Films run at 24 frames per second, and every one of those frames has motion blur baked into it by the camera. So fast movement on film reads as a smooth streak. Your interface has no camera. Every frame is drawn razor sharp. Move something fast enough and it stops looking like a streak and starts looking like a row of separate copies, which is why fast interface motion sometimes strobes.

Hand drawn animators solved this decades ago by stretching the shape along its path for the few frames where it is moving fastest. Those are called smear frames, and good interface motion still quietly uses the same trick.

Media slot 7
A smear frame example: a fast moving UI element with a single stretched frame visible when you step through it, shown both at full speed and frame by frame. Build in After Effects. Everything sourceable is character animation, which misses the point that this idea transfers to interfaces.

Try it yourself

Move the damping slider and drop the card in. Find your own line between landed, playful and drunk.

Stage 6

The aftermath

Three things happen to an animation after it has played once, and almost nobody designs for any of them.

It hands over to something else

The loader finishes and the success state begins. The join between those two is where the work either looks finished or looks assembled from parts.

The example everyone still copies is Michaël Villar's payment button. The button squashes into a spinner, and the spinner resolves into a tick. It is one object the whole way through. Nothing gets destroyed and rebuilt.

If you are crossfading instead of morphing, borrow the rule from film editing. The thing leaving should go faster than the thing arriving, and the arriving one should start slightly late. Roughly 100 milliseconds out, 150 milliseconds in, starting about 50 milliseconds behind. Two fades with identical timing feel wrong to everybody and almost nobody can explain why. The reason is that for a moment both are half visible, so you are reading neither of them. The Next.js view transitions guide recommends the same shape.

Media slot 8
The button to loader to success morph, one continuous element throughout: rounded button compresses into a circular spinner, spinner stroke resolves into a tick. Flat, single accent colour, 2 to 4 seconds total. Villar's original clips were hosted on cl.ly and are dead, so this needs a faithful recreation; credit him either way.

It gets interrupted

Someone taps again while it is still moving. This part is well understood on the engineering side. CSS transitions redirect smoothly from wherever they currently are. Keyframe animations snap. Springs redirect cleanly because they already carry speed. The View Transitions API jumps straight to the end.

What almost nobody has written down is what an interruption should feel like. Every major design system is quiet on it. That silence is itself the useful finding. Design the interrupted state deliberately and you are ahead of Material, Fluent and Apple all at once.

Try it yourself

Open the panel, then close it before it lands. Try all three and see which one handles being interrupted well.

It repeats

Forty times. Four hundred times.

Psychologists have studied this for a century and call it habituation. Your reaction to something gets weaker every time it repeats. Motion systems have barely acknowledged it. No mainstream design system scales an animation down as its action becomes more frequent. Apple's guidelines come closest by telling you not to animate frequent interactions much at all.

So your animation charges the same price every single time, while what the user gets out of it drops towards nothing. That celebration you were so happy with is lovely on day one and a speed breaker by week two. Bas, ho gaya, let me through.

The way out is to decide by frequency. Something that happens forty times a day gets 150 milliseconds and no flourish. Something that happens once a month can have its full second. Counting how often it fires is a far better input than arguing about how important it is, and nobody ever asks for it in review.

Try it yourself

Watch the same success animation as if it were your first time, your tenth, and your fortieth.

The making-of layer

This section exists because of one expensive afternoon.

I had built an After Effects composition full of gaussian blur and blend modes. It looked genuinely beautiful in preview. I exported the JSON, opened it on a phone, and watched the app strip it down to a flat grey shape. Weeks of work, paani mein. I had never learned the difference between what my software can draw and what the phone will actually agree to draw.

You have about ten milliseconds per frame. At 60 frames per second each frame is 16.7 milliseconds, and roughly 10 of those are actually yours once the browser has taken its share. At 120 frames per second, halve it. A 300 millisecond animation is around eighteen frames, and every one of them has to be paid for. People spot a dropped frame immediately, even if they cannot name what they saw.

There are two lanes, and only one of them is fast. Browsers can move transform and opacity on the compositor, which is cheap and stays smooth even when the rest of the app is busy. Almost everything else, like width, top, box shadow and background, forces the browser to recalculate layout or repaint on every single frame, in the same lane as all your other code. That is where jank comes from. If you take one engineering fact from this page, take this one: if it moves, move it with transform. Animating left and animating translateX look identical in Figma and behave completely differently on a mid range Android phone.

Lottie will lie to you in preview. The After Effects to Bodymovin to JSON pipeline is my daily workflow, and the list of supported features is required reading before you draw anything at all. Expressions are web only. Most effects do not export. Gaussian blur does not work on iOS. Blend modes effectively fail on native. Your desktop preview is the best case you will ever see, and every device after that is worse. If your animation leans on blur or blending, flatten it, rasterise it, or rebuild it out of clean shape layers. Then test the actual JSON on the actual players, every time.

Sometimes Lottie is the wrong tool. For a simple icon changing state, fifty lines of CSS beat it on file size, on performance and on how easy it is to change later. Rive beats it when your animation has states. One Rive file can hold a button's entire life, idle to hover to loading to success, driven by inputs from your code instead of a pile of JavaScript glue, at a fraction of the size. You pay for that with a heavier runtime and by leaving After Effects behind. My order is CSS first, Lottie when the artwork is genuinely complex, Rive when the states are.

Reduced motion is not a nice to have. WCAG 2.3.3 exists because motion physically makes some people ill. Balance and vestibular problems affect around 35% of adults over 40, and parallax and zoom are the worst offenders because they imitate the feeling of moving your own body. The right response to prefers-reduced-motion is to simplify, usually by swapping movement for a crossfade, rather than removing all the feedback and leaving people guessing. This page does exactly that. Flip the toggle at the top right and watch every demo change.

How one of these actually gets made at my desk. Shapes drawn in Illustrator with deliberately simple paths. Layers named properly, as though I am being charged per character. Imported into After Effects as shape layers, with precomps only where the file would otherwise be unmanageable, because they make the JSON bigger. Animated strictly inside what the supported features list allows. Exported through Bodymovin. Then I open the JSON and read it, because the file size tells you the truth about your layer discipline when nothing else will. screenshots of the actual Illustrator layer panel, the AE graph editor with a real curve, and a before/after JSON size from a real project. Own files, no sourcing needed.

Media slot 9
Screen recording or annotated screenshots of an After Effects graph editor showing a speed curve being adjusted on a real shape layer, with the look of an actual working file rather than a polished tutorial. Own material.

Outro

That is the whole life of one animation.

It gets triggered. It waits, or it doesn't. It winds up, or it doesn't. It travels along a curve that gives it a personality. It arrives, it settles, and then it has to live with what comes next: handing over, getting interrupted, and being repeated until nobody notices it any more.

Every single one of those is a decision, and you can make each one on purpose.

The numbers here are mine, from the products I have worked on. Yours will be different. Material and Apple are further apart from each other than either is from me, and all three of us are shipping. Take the reasoning and leave the values.

Now go and watch your own animations forty times in a row. That is where the truth is hiding.

Full reference list

Research

Specs and platform docs

Books and essays