What does animation do?
Motion in an interface explains what happened: where an element came from, where it went, whether a press was registered. Everything that does not do this is decoration, and decoration has its own small budget. This skill helps spend that budget precisely: without it the model animates everything with the same fade-up.
The skill is self-contained. If ui-ux (style and interface rules) and front (code and stack) are installed alongside it, they complement it.
Three questions first
- What is this motion for? Feedback on an action, a link between states, drawing attention to one important thing, the character of the brand. If there is no answer, do not animate.
- How often will the person see it? The budget depends on the answer (next section).
- What already exists in the project? Look at the durations, curves and animation library in use and continue in the same spirit. A new library for the sake of one effect is almost always a mistake.
How much animation is appropriate
The main rule: the more frequent the action, the less animation. What delights on the first viewing irritates on the hundredth.
| How often the user sees it | What to do |
|---|---|
| Hundreds of times a day (keyboard shortcuts, command palette, switching tabs) | No animation |
| Dozens of times a day (menus, tooltips, hover) | Very fast, up to 150 ms, or no animation |
| Occasionally (dialog, side panel, notification) | An ordinary 200–300 ms transition |
| Rarely or once (onboarding, success screen, the first screen of a landing page) | Can be expressive |
Level by project type:
- App (used every day): restrained. Control states, layers entering and leaving, smooth layout changes. Everything under 300 ms. Nothing moves without a user action.
- Showcase (landing page, website, promo): noticeable. One orchestrated moment on the first screen, blocks revealing on scroll, live details on hover. The rest is calm.
One expressive moment per screen, quiet everywhere else. Animation on everything at once is as much a sign of a template as having none.
Do not animate: keyboard-triggered actions, theme switching, context menus, anything the user does many times in a row.
Default taste
The skill owner can edit this section to match their own preferences. The user's words in the current request take precedence.
Welcome on showcase surfaces:
- Reveal on scroll — sections and large objects softly appear when scrolled to. Once, without repeats.
- Scroll-linked scenes — a pinned section where scrolling drives the animation and explains something about the product. One or two per page; scrolling itself stays ordinary, its speed and direction are never hijacked.
Do not use unless explicitly asked:
- Glow and gradient borders — shimmering outlines, neon glow, animated gradient backgrounds. Emphasis comes from motion and typography, not light.
Libraries: CSS first; when it is not enough in React — Motion; GSAP only for complex scroll scenes. Details are in references/tools.md.
The character of motion is "connected and precise".
- Flows inside an app. Screens melt into each other rather than being swapped: one "hero" object travels through every step, text turns into text through a blur, only what changed changes, a new layer grows out of its source. If the task has a sequence of screens or states, read
references/continuity.mdfirst and assign a hero. - Landing pages and websites. One curve for the whole site with a sharp start and a long soft deceleration, no bounce; the headline assembles word by word; large things appear out of a blur; one text scene on scroll; everything in CSS. Recipes with exact values are in
references/showcase-recipes.md.
What both share: blur together with opacity as the material of a transition, overlapping enter and exit instead of a queue, no bounce, and one consistent curve. If the project's style calls for a different character (terminal, retro), see the table in references/patterns.md.
Durations
| What | Duration |
|---|---|
| Response to a press, hover, the toggle itself | 100–150 ms |
| Tooltip, dropdown menu, a small entrance | 150–200 ms |
| Dialog, panel, sheet | 200–300 ms |
| Content changing in response to an action (price, counter, chart) | 300–500 ms |
| Page transition, a large layout change | 300–500 ms |
| Decorative scenes on showcase surfaces, with no user involvement | up to 800–1000 ms |
- Exit is shorter than enter by about a third: what is leaving is no longer interesting.
- The longer the path and the larger the area, the longer the duration; a small element at 400 ms looks sluggish.
- When rules overlap, the shorter one wins. The control itself always responds in 100–150 ms; what it changed may take longer to finish, but the user must not have to wait for the animation to end before acting again.
Curves and springs
- Entering — ease-out: a fast start and a soft stop, which feels responsive.
- Leaving — also ease-out, but shorter. Some design systems use an accelerating curve for exits, but its slow start feels like a delay, so it is not used here; the skill owner can change this rule.
- Moving across the screen from point to point — ease-in-out.
- Linear — only for continuous motion: a spinning indicator, a marquee, progress.
Default tokens:
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* main curve: sharp start, long deceleration */
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--duration-fast: 160ms; /* response: color, opacity */
--duration-base: 300ms; /* layers, background and shadow of controls */
--duration-slow: 450ms; /* content melting into content */
--duration-reveal: 800ms; /* blocks appearing on showcase surfaces */
}
One curve for the whole project: when every part of a transition uses it, they read as a single movement. With this curve a response can last 200–450 ms and still feel instant, because most of the change happens in the first 100 ms.
Springs beat curves when a gesture drives the motion or the animation can be interrupted midway (dragging, a sheet, a list reordering): they preserve velocity and do not jerk. Bounce is only for movement and scale; for color and opacity it is always zero. Noticeable bounce suits playful styles and irritates in working tools.
Execution rules
- Animate
transformandopacity. Width, height, margins and position trigger layout recalculation and cause jerks. To change size usescale, the FLIP technique or a library's layout animation. - Blur is the permitted exception.
filter: blur()up to 12px together with opacity is the signature material of a transition, but it costs more: apply it to small blocks (a heading, a figure, an icon, a card), never to a whole screen, and test on a phone. - Enter and exit overlap. What is leaving and what is arriving coexist for 30–50% of the duration. A queue of "first it vanished, then it appeared" breaks the connection and doubles the time.
- Only the difference moves. What did not change (digits, words, icons) stays in place.
- Never start from
scale(0). Nothing in life appears from a point: start at 0.9–0.96 together with opacity. transform-originsits at the source. A menu grows out of its button, not from the center.- Press:
scale(0.97)on:activegives the feel of a physical button. - Interruptibility. Build interactive motion with
transition, not@keyframes: a transition can be reversed midway, keyframes cannot. - Roles first, timing second. When several elements move in response to one event, assign a single lead; the rest are support, decoration or static. Two leads is a layout problem, not an animation one.
- One entrance per container. If the panel slid in, its content is already there: do not add a stagger of children on top of the parent's entrance.
- What leaves frees its space immediately, so the neighbors close in while it fades, not after.
- Exit mirrors enter and happens all at once. What came in from the right leaves to the right; a group disappears simultaneously, with no reverse stagger.
- Direction follows meaning: "forward" enters from the right, "back" from the left.
- Stagger: a 30–80 ms step between elements, the whole cascade no longer than 300–400 ms; after the sixth or seventh element the rest appear together. On the first screen of a showcase the step may go up to 100–150 ms.
- Gestures use springs and never block. The element follows the finger one to one, can be grabbed midway, and after release picks up the velocity of the gesture. Bounce only after a throw.
- Tooltips: a delay before the first one, the next ones in the same group appear immediately and without animation.
- Reveal on scroll happens once. A block that hides and reappears on every pass is tiring.
- The page is whole at rest. Content must not depend on whether a script ran: the hidden starting state is set only together with the animation being enabled, never in the base styles. Otherwise, when a script fails, in previews and in screenshots, the user sees an empty screen.
- Hover changes one property, not scale, lift and shadow all at once.
will-change— sparingly and only for the duration of the animation, not on everything.
Accessibility
This is not optional: motion on screen causes dizziness and nausea for some people.
prefers-reduced-motion: reduce: remove movement, scale, rotation, parallax and autoplay; keep the smooth change of opacity and color. Switching everything off deprives the person of feedback. The most reliable approach is to declare motion only where it is allowed:
.card { transition: opacity var(--duration-base) var(--ease-out), background-color var(--duration-fast); }
@media (prefers-reduced-motion: no-preference) {
.card { transition-property: opacity, background-color, transform; }
.card:hover { transform: translateY(-2px); }
}
- Anything that moves on its own for longer than 5 seconds (a marquee, a carousel, background video) has a pause button — a WCAG 2.2.2 requirement.
- Nothing flashes more than three times a second.
- Keep motion over a large area (parallax, background scaling) at a small amplitude.
- Animated text stays readable to a screen reader: a per-character split gets an
aria-labelwith the whole phrase, and the pieces getaria-hidden.
Verification
- Watch the animation in a browser, not only in the code; if you cannot, tell the user it was not verified live.
- Slow it down 4–10× in developer tools: jerks, a wrong growth origin and unnecessary properties become visible.
- Press quickly several times in a row: the animation must interrupt and reverse, not pile up in a queue.
- Turn on "reduce motion" in the system and make sure the interface still works and stays understandable.
- A screenshot taken right after scrolling may show an empty space where a block has not yet appeared — a reason to check the "the page is whole at rest" rule.
Review mode
When asked to assess or fix an existing animation, report the findings as a table:
| Where | Before | After | Why |
|---|---|---|---|
Modal.tsx:18 | scale(0) → 1, 500 ms, ease-in | scale(0.96) + opacity, 220 ms, ease-out | appears from a point and lags |
Reference files
references/continuity.md— connected animation: the hero of a flow, screens melting into each other, numbers changing digit by digit, collapsing on scroll; the techniques and how to build them on the web. Read for any sequence of screens or states.references/choreography.md— a group of elements reacting to one event: roles (lead, support, decoration, static), relationships within a pair (together, overlap, sequence, carry), staggers, direction, exit, interruption. Read whenever more than one element moves.references/gestures.md— everything that is dragged, swiped and thrown: finger tracking, interruptibility, springs, velocity handoff, momentum projection, soft boundaries. Read for sheets, carousels, sliders, drag and drop.references/showcase-recipes.md— landing page recipes with exact values: a word-by-word headline, appearing out of a blur, a drawn underline, a card cascade, text on scroll. Read for the first screen and sections of a site.references/patterns.md— a catalog of techniques: micro-interactions, entrances, number changes, scroll, page transitions, text; when each works and when it harms; the character of motion by style.references/tools.md— a tool ladder from CSS to GSAP with code examples and selection rules.