Guides · · Maxwell Prehoda
How Long Should UI Animations Be? 13 Duration Rules With the Real Numbers From Material, Apple and Carbon
Short answer: most UI animations should run 150 to 300 ms. Tiny feedback like a toggle or a hover sits at the bottom of that range or under it, a modal or panel sits at the top, and only large moves across a big screen earn 400 ms or more. Exits run a little faster than entrances, and anything people trigger dozens of times a day, or from the keyboard, should be shorter still or not animate at all.
Those numbers are not folklore. Below are the rules as the people who set them wrote them: Nielsen Norman Group's research, the duration tokens Google, IBM and GitLab ship in their design systems, Apple's Human Interface Guidelines and the defaults in Tailwind and SwiftUI. Each one links to the source, and most come with a live demo from our directory so you can feel the timing instead of reading about it. We checked every number against the source page in November 2026.
1. Nielsen Norman Group: 200 to 300 ms for real screen changes: Best for modals, panels and other substantial screen changes
Platform: Research article, NN/g (Page Laubheimer, 2020)
NN/g's "Executing UX Animations: Duration and Motion Characteristics" is the most quoted source on this topic, and it is refreshingly specific. Its general range is 100 to 500 ms. Simple feedback like a checkbox sits around 100 ms, a substantial change such as a modal entering the view sits at 200 to 300 ms, and 400 ms is the ceiling, kept for large movements across big screens. At 500 ms and above, the article says, animation starts to feel like a drag.
The rule of thumb it gives is the one to tape to your monitor: look for the shortest time an animation can take without being jarring. It also warns that animations are far more often too long than too short, and that a gap as small as 250 versus 300 ms can feel different, so test on the device instead of trusting a number.
Our Fade In Down below is the dropdown entrance most menus use. The demo plays at 0.5 s so you can watch it; for a real menu, set it to 200 to 250 ms and it lands right in NN/g's band.
Watch out for: Designers tune timing in prototypes they watch over and over, which makes everything feel slow, so they speed it up; the opposite also happens in screen recordings. Judge durations by using the real UI at normal speed.
2. Jakob Nielsen's 0.1 second limit: instant feedback: Best for toggles, checkboxes and press states
Platform: Usability research, NN/g (response time limits)
Nielsen's three response time limits predate CSS animation, but they set the frame for every duration choice. 0.1 seconds is about the limit for a system to feel like it reacts instantly, 1 second is about the limit for a user's flow of thought to stay uninterrupted, and 10 seconds is about the limit for keeping attention at all.
For animation, the useful reading is this: the response to a press must begin within 100 ms, even if the motion that follows runs longer. A toggle can take 250 ms to slide across as long as it starts moving the moment it is touched. If the state change waits for a delay or a slow ease-in, the control feels broken, whatever the total duration says.
Our iOS Toggle Switch below starts on the click: the track colour changes over 0.25 s and the knob slides over 0.3 s on a curve that is fastest at the start, so it reads as instant even though the full motion is longer than 100 ms.
Watch out for: Never add an animation-delay to direct feedback. A delay on a press state is the fastest way to make a fast app feel laggy.
3. IBM Carbon: six tokens, productive and expressive: Best for products with both task screens and marketing moments
Platform: Carbon Design System, free and open source
Carbon publishes one of the clearest duration scales anywhere: fast-01 at 70 ms for buttons and toggles, fast-02 at 110 ms for fades, moderate-01 at 150 ms for small expansions and short moves, moderate-02 at 240 ms for expansion and toasts, slow-01 at 400 ms for large expansion and important notifications, and slow-02 at 700 ms for background dimming. Its review checklist says micro-interactions should land between 90 and 120 ms.
The idea worth stealing is the split between productive motion (task screens, fast, out of the way) and expressive motion (moments of delight and big reveals, slower and more noticeable). Each mode has its own curves, and Carbon says plainly that productive motion is significantly faster. The scale is also deliberately non-linear, so a move four times as long does not take four times as long.
Our Circle Reveal below is expressive motion: an iris opening over 0.9 s. That is fine for a hero image or a launch moment and far too slow for a dialog in a task flow.
Watch out for: Carbon's 70 ms is fast enough that some fades become invisible on low refresh-rate displays. Use it for colour and state changes, not for anything that has to be followed with the eye.
4. Material Design: duration grows with distance: Best for drawers, sheets and anything that travels far
Platform: Material Design 3 tokens (Android, Compose, Material Web)
Material's motion tokens run in sixteen steps: short1 to short4 at 50, 100, 150 and 200 ms, medium1 to medium4 at 250 to 400 ms, long1 to long4 at 450 to 600 ms and extra-long1 to extra-long4 at 700 to 1000 ms. The guidance that goes with them is one sentence: duration should increase as the area or traversal of an animation increases, so the sense of speed stays consistent.
That is why a bottom sheet that crosses the whole phone takes longer than a chip that changes colour, and why the same drawer needs a longer duration on a tablet than on a phone. Keep the speed constant, not the duration.
Our Slide In Left below travels a long way, nine em, on a drawer curve that is fast out of the gate and glides into place, over 0.7 s. A short nudge of one em at the same duration would feel sluggish; that is the rule in action.
Watch out for: Do not scale durations linearly with distance. Twice the travel should get a little more time, not twice the time, or long moves will drag.
5. Material container transform: exits run shorter: Best for dismissals, toasts and closing dialogs
Platform: Material Components for Android
Material's own transitions encode a rule most teams forget. The container transform defaults to 300 ms incoming and 250 ms outgoing, and the fade transition is shorter going out than coming in. NN/g gives the same advice with the same shape: a popup might take about 300 ms to appear and 200 to 250 ms to disappear.
The reasoning is simple. When something arrives, people need to see where it lands. When something leaves, they have already decided they are done with it, and every extra millisecond is a wait. Exits also usually use an ease-in or accelerate curve, so they gather speed and get out of the way.
Our Zoom Out below is the classic modal or lightbox close: it shrinks on an ease-in cubic and fades in its second half. In production, run it at roughly two thirds of your entrance time.
Watch out for: If an exit is slow and blocks input until it finishes, people will click through it and hit whatever is underneath. Make closing elements ignore pointer events once the exit starts.
6. GitLab Pajamas: 100 ms and 200 ms for hover and focus: Best for hover and focus states in dense product UI
Platform: Pajamas Design System, open source
GitLab's design system gives a short, practical table: 100 ms for list item hover and focus, 200 ms for hover and focus on interactive elements, 500 ms for action feedback and 600 ms for position changes and complex transitions. Its default hover curve is plain `ease`, and focus and action animations use an ease-out cubic.
The split between 100 and 200 ms matters in dense screens. A list with fifty rows that each take 200 ms to highlight leaves a trail of half-lit rows as the mouse moves down it; at 100 ms the highlight keeps up with the pointer. Buttons, which people aim for one at a time, can afford the extra 100 ms.
Our Outline to Solid Button below fills on hover with a 0.2 s background and colour transition, exactly the Pajamas value for an interactive element.
Watch out for: Hover does not exist on touch screens. Never put information or a required step behind a hover animation, whatever its duration.
7. Tailwind CSS: the 150 ms default you already ship: Best for Tailwind projects that never set a duration
Platform: Tailwind CSS v4, free
If your project uses Tailwind and you write `transition` without a duration, you are shipping 150 ms on cubic-bezier(0.4, 0, 0.2, 1). Both come from CSS variables, `--default-transition-duration` and `--default-transition-timing-function`, so you can change them in one place for the whole app.
150 ms is a sensible default for colour, opacity and small hover changes. It is too fast for anything that moves across the screen, which is where `duration-200` to `duration-300` belong. A quick audit is to search your codebase for `duration-500` and above and ask whether each one is decoration or feedback.
Our Underline Grow Link below ships with a Tailwind version that uses `duration-300` for the underline, a deliberate step up from the default because the line has to travel the width of the text.
Watch out for: Applying `transition-all` with a duration animates every property that changes, including layout ones like width and padding. Name the properties you mean.
8. Apple HIG: skip motion on frequent interactions: Best for actions people repeat dozens of times a day
Platform: Apple Human Interface Guidelines
Apple's guidelines give no millisecond table, but they give the rule that decides more durations than any table: in apps, generally avoid adding motion to UI interactions that occur frequently. The system already animates its standard controls subtly; a custom element should not make people spend extra time watching motion every time they use it.
Two more lines from the same page belong next to it: aim for brevity and precision in feedback animations, and let people cancel motion, so nobody waits for an animation to finish before they can act, especially one they will see again. Apple also says to make motion optional and never the only way important information is communicated.
In practice, frequency is a multiplier on duration. A celebration that plays once after onboarding can take a second. The same flourish on every saved draft is a tax.
Watch out for: "Let people cancel motion" means the UI accepts input during the animation. If your animation library locks interaction until a transition completes, the duration is now a hard wait.
9. Emil Kowalski on Raycast: keyboard actions get zero: Best for command menus and keyboard shortcuts
Platform: Essay, emilkowal.ski
Emil Kowalski, who built Sonner and Vaul, writes that UI animations should usually be shorter than 300 ms and that fast animations improve perceived performance. Then he goes further: never animate keyboard-initiated actions. His example is Raycast, which people open many times a day; a 500 ms entrance there would be maddening, and Raycast has no open animation at all.
The point is that zero is a valid duration. A command palette, a shortcut that switches tabs or a list you move through with arrow keys is driven by someone who already knows what they want. Motion there slows them down and adds nothing they need to track.
If you do keep a little motion on a palette for mouse users, keep it at the very bottom of the range, around 100 to 150 ms, and drop it when the palette is opened from the keyboard.
Watch out for: Removing an animation is not the same as removing feedback. A keyboard action still needs a clear selected state; it just should not wait to show it.
10. SwiftUI and Material springs: think in perceived duration: Best for spring-based motion in SwiftUI, Compose or CSS linear()
Platform: SwiftUI (Apple), Material 3 (Android)
Springs do not have a fixed end time, so modern frameworks describe them by how long they feel. SwiftUI's `.smooth` spring defaults to a 0.5 s perceptual duration with no bounce, and Apple defines that duration as roughly the settling time, the pace of the spring. Material 3's spring tokens pick speed by size: small components like switches use the fast spring, full-screen animations the slow one, and everything else the default.
That gives you a translation table. A spring that feels like 300 ms suits a card; 500 ms suits a sheet. Bounce adds perceived time, so a bouncy spring needs a shorter base duration to feel as quick as a flat one.
On the web you can get the same feel in pure CSS with `linear()`. Our Elastic Spring below uses a `linear()` spring curve with a cubic-bezier fallback for older browsers; the demo loops slowly so you can see the overshoot and settle.
Watch out for: A spring that overshoots looks playful on a card and wrong on a destructive confirmation or a data table. Keep bounce for elements people grab or flick.
11. WCAG 2.2.2 and GitLab skeletons: loops have their own clock: Best for loaders, skeletons and ambient loops
Platform: W3C WCAG 2.2 (Level A), Pajamas
Looping animation follows different rules from transitions. The cycle should be slow enough to read as calm: GitLab's skeleton loader is a horizontal pulse on linear timing over 1 s. Go much faster than a second a cycle and a loader stops reading as calm progress and starts reading as alarm.
The hard limit comes from accessibility. WCAG 2.2 Success Criterion 2.2.2, Pause, Stop, Hide, is Level A: any moving, blinking or scrolling content that starts automatically, lasts more than five seconds and sits alongside other content needs a way to pause, stop or hide it. A loader that disappears when content arrives is fine; a decorative background that loops forever needs a control or a reduced-motion fallback.
Our Skeleton Shimmer below sweeps every 1.5 s on ease-in-out. Like every loader in our directory, its copyable CSS slows the cycle to 3 s under `prefers-reduced-motion` instead of freezing it, so the page still shows it is working.
Watch out for: Do not use a looping loader for waits under about a second. It flashes on and off and makes the app feel slower than showing nothing.
12. Our Staggered List Entrance: 90 ms between rows: Best for lists and grids that load together
Platform: Motions directory, free, pure CSS Ours
Stagger is where durations quietly add up. Microsoft's Fluent 2 guidance says to use short offsets between items and keep the total duration in mind, and that is the whole trick: ten rows at 0.6 s each with a 90 ms offset take 1.4 s to finish, which is already long for a list.
Our version puts each row's index in a `--i` custom property and sets the delay to `calc(var(--i) * 90ms)`, so adding rows needs no new CSS. For long lists, cap the index (stagger only the first six to eight rows and show the rest at once) so the total stays under a second.
Like every snippet in the directory, the copyable CSS includes a `prefers-reduced-motion` guard that jumps straight to the final state.
Watch out for: Never stagger content people are waiting to read, such as search results after they hit Enter. Stagger the first load of a dashboard, not every refresh.
13. Our creator: put the duration in the brief: Best for custom animations with your timing baked in
Platform: Motions creator (paid plans; a full run is free to try) Ours
Most animation code you find online, including generated code, uses showcase timings: 600 ms fades and one second slides that look great in a demo and slow in a product. The fastest fix is to state the numbers up front.
Describe the animation in our creator, or paste your own component as HTML or a screenshot, and include the durations from this page: "enter 250 ms ease-out, exit 180 ms ease-in, hover 150 ms". It answers up to four quick questions while the animation takes shape and gives you production-ready CSS keyframes, which you can refine in chat and export.
If you already have a snippet from our directory, the same approach works in reverse: copy it, then ask the creator to retime it to your design system's tokens.
Watch out for: A model will follow the timing you give it, including a bad one. Use the ranges on this page as the starting point and check the result on a real device.
How to choose a duration in under a minute
Three questions get you to a number. Start in the middle of the range they point to, then shorten it until the motion starts to feel jarring, and stop one step before that.
Match it to the size of the change
Colour, opacity and hover: 100 to 150 ms (Carbon fast tokens, Tailwind's default, GitLab's list hover). Small moves and expansions: 150 to 250 ms. Modals, sheets and panels: 250 to 300 ms (NN/g). Large moves across a big screen: 400 ms, up to Material's long tokens for full-screen changes. Exits get about two thirds of the entrance time.
Match it to how often it happens
Something seen once, like onboarding or a launch reveal, can use expressive timing up to a second. Something seen every few minutes should stay under 300 ms. Something triggered constantly or from the keyboard should be under 150 ms or have no animation, as Apple's guidelines and the Raycast example argue. When in doubt, frequency wins over beauty.
Match it to who is waiting
Feedback must start within 100 ms (Nielsen), even if it finishes later. The whole response should land within about 400 ms (the Doherty threshold) for a flow to feel unbroken. Loops are judged per cycle, around 1 to 1.5 s for skeletons, and need a pause or reduced-motion fallback if they run longer than five seconds next to other content (WCAG 2.2.2).
Retime one screen today
Pick the screen people use most, list every transition on it and write its duration next to it. Anything over 300 ms that is not a one-off moment is a candidate to cut, and anything a keyboard triggers is a candidate to remove. Then put the survivors on a small scale of tokens, four or five values, so the next person does not invent a sixth.
If you want a new animation that starts with sensible numbers, grab one from the Keyframe Animations directory and retime it, or describe it to our creator with the durations from this page in the brief. For curves, our easing function examples pair with every rule above.
Make a dialog open and close animation in pure CSS keyframes. Open: 260 ms, fade plus a 12px rise, ease-out cubic-bezier(0.22, 1, 0.36, 1). Close: 180 ms, fade plus a slight scale to 0.97, ease-in. Backdrop: fade over 200 ms, starting with the dialog, no delay. Under prefers-reduced-motion, keep a 120 ms opacity fade and drop all movement.
Common questions
What is the best duration for UI animations?
For most UI transitions, 150 to 300 ms. Use about 100 ms for simple feedback like toggles and checkboxes, 200 to 300 ms for modals and panels, and keep 400 ms or more for large movements across big screens. NN/g's research puts the ceiling around 400 ms and says 500 ms and longer starts to feel like a drag.
Should exit animations be faster than entrance animations?
Yes. Material's container transform uses 300 ms in and 250 ms out, and NN/g suggests about 300 ms to appear and 200 to 250 ms to disappear. People need to see where something lands, but they have already moved on when it leaves.
What are Material Design's animation duration tokens?
Material 3 defines sixteen duration tokens: short1 to short4 (50, 100, 150, 200 ms), medium1 to medium4 (250, 300, 350, 400 ms), long1 to long4 (450, 500, 550, 600 ms) and extra-long1 to extra-long4 (700, 800, 900, 1000 ms). Duration should increase with the area or distance the animation covers.
Is 500 ms too long for an animation?
For a routine UI transition, usually yes. NN/g describes 500 ms and longer as feeling like a drag, and Emil Kowalski recommends staying under 300 ms. 500 ms can work for a one-time, expressive moment, a full-screen change on a large display, or as the perceived duration of a soft spring.
How long should a hover transition be?
About 100 to 200 ms. GitLab's Pajamas system uses 100 ms for list items and 200 ms for interactive elements, and Tailwind's default transition is 150 ms. Longer hovers leave a visible trail when the pointer moves across many items.
Sources
- NN/g: Executing UX Animations, Duration and Motion Characteristics
- NN/g: Response Times, The 3 Important Limits
- Material Components for Android: Motion theming
- Carbon Design System: Motion
- GitLab Pajamas: Motion
- Apple Human Interface Guidelines: Motion
- Apple SwiftUI: smooth(duration:extraBounce:)
- Tailwind CSS: transition-property
- Emil Kowalski: Great Animations
- W3C: Understanding SC 2.2.2 Pause, Stop, Hide
- Laws of UX: Doherty Threshold
- Fluent 2: Motion