Judge · Taste
Training judgement

Training judgement

Emil Kowalski’s Train Your Judgement turns the previous section into a drill. The premise is stated in its first line: “AI can write animation code. What it can’t do is know what feels right.” It produces motion that works but feels mediocre, and if you cannot tell the difference, you will ship it and settle for good enough, which he says is not good enough. The format is the method. Each exercise shows two animations side by side. Your job is to pick the better one, write down why you chose it, and only then read his breakdown. Putting the reason into words, he writes, trains your ability to articulate your , “a skill that will be incredibly valuable in the AI era.” The figure below rebuilds three of his comparisons with his own values; the page itself has eleven. Open it and do the exercises before reading the walkthrough that follows, because the walkthrough spoils them.

A popover appears. Which entry feels better?

Trigger
Trigger

Pick the one that feels better. There is a reasoned answer, and it appears once you commit.

Adjust
Figure 1. Which feels better. Three of Emil Kowalski's side-by-side comparisons, rebuilt with his values. Replay both, decide, then read his reasoning. The point is not to be right; it is to notice what you noticed.Constants from the source

The first pair is a full-screen mobile menu at two durations. Emil’s rule of thumb, keep UI animations under 300ms, holds for tooltips, dropdowns, and buttons, but a full-screen menu travels much further, so a short duration feels jarring. Emil’s takeaway is that duration should scale with the distance travelled: bigger elements are heavier and should animate slower, “the same way a truck takes longer to stop than a bicycle.” The second pair is a toast entering with ease-in versus ease-out. Ease-in starts slow and speeds up, which makes the interface feel sluggish; ease-out starts fast, giving instant feedback, and decelerates gently into place, which also simply feels faster because the curve is sharp at the start. Entry animations get ease-out.

The third pair is an element scaling in from 0 versus from 0.9. scale(0) looks like the element came out of nowhere; a higher initial value resembles the real world, “just like a balloon, even when deflated it has a visible shape.” Start from 0.90 to 0.95 so the element feels like it was always almost there. The fourth pair, an accordion with and without bounce, is the one where Emil refuses to pick: neither is universally right. For a learning app the bounce adds energy; for a finance app the same bounce feels unserious. Bounce communicates personality the way easing intensity does, so the default is zero and you add it intentionally when the brand calls for it. The fifth pair is a hover highlight in a list, instant versus faded. The fade looks smoother in a demo, but move quickly and the highlight trails your cursor, always one step behind. For something you touch hundreds of times a day, the direct connection matters more than smoothness; Emil uses Raycast that often and notes that it does not animate when it opens, because that delight would turn into annoyance. Invisible details covered the same idea as frequency and novelty.

The next three are about mechanics. A button pressed to scale 0.9 loses a tenth of its size, which is too much in most cases; at 0.97 the compression is barely visible but still felt, and “subtlety reads as quality.” Removing a chip from a row compares Motion’s AnimatePresence in its default mode, where the exiting chip stays in flow until its animation completes and the siblings slide over afterwards, with mode="popLayout", which pulls the exiting element out of document flow on the first frame so the remaining chips start moving at the same time as the exit plays. Both versions animate smoothly; the difference is sequencing, and the parallel one feels tight. Handling interruptions compares a menu built with keyframes, which jump to their new position when toggled mid-animation, against CSS transitions, which retarget smoothly. For anything that can be toggled rapidly, menus, modals, accordions, drawers, prefer transitions.

The last three are about relationships between elements. A popover that animates in from the middle of nowhere has no connection to the button that triggered it; one that comes from the button creates cause and effect, “I clicked this, and this appeared from it.” The default transform-origin of center is wrong for almost every triggered element, and Radix UI and Base UI expose CSS variables for the trigger position. A hero section staggered with identical timing on every element is technically staggered but feels artificial, with the same effect on motion as a linear easing; the better version lets the title appear first and get the most screen time, gives the subtitle and buttons increasing delays, and only fades the small pill at the top because it is the least important element. The point is hierarchy, not a single right choreography. Finally, a side panel that slides in and then staggers each menu item is two layers of entrance; the panel arrives, then you wait for items to trickle in. One could call it delightful, Emil writes, but that does not make it good. The panel that slides in with its content already there is faster, cleaner, and readable immediately. “Sometimes the best animation is no animation.”

The same criteria appear, stated as principles, in two earlier posts. Great Animations says great animations feel natural (the Dynamic Island, springs rather than instant changes), are fast (ease-out, usually shorter than 300ms), have a purpose (pace them, consider frequency, never animate keyboard-initiated actions), are performant (transform and opacity, hardware acceleration when the main thread is busy), are interruptible, are accessible under prefers-reduced-motion, and feel right as a whole: Sonner’s toast is slightly slower than usual and uses ease rather than ease-out because that fits the vibe of the whole library. Good vs Great Animations adds origin-aware popovers, ease-in-out for things already on screen (a car accelerating and decelerating), custom curves because the built-in ones are not strong enough, springs for decorative mouse-driven changes and no animation at all for a functional banking graph, and a tabs example where the highlight bar and text colour only look wrong in slow motion, which clip-path fixes. Two habits from those posts belong to the method: play the animation frame by frame or in slow motion to find what feels off, and review your work the next day with fresh eyes.

Read together, the drill has three moves. Recreate: build the thing you admire, or two versions of the thing you are building, because as Emil says in Building an animation course, students have to feel the difference between good and bad themselves, “like touching a physical object to understand its texture.” Compare: put the versions side by side and choose, which is what his course platform and the exercises do. Articulate: write the reason down before you read anyone else’s. Rauno Freiberg names the first move explicitly in Invisible Details, calling recreation and reflection two ways to build a stronger design intuition and vocabulary, so the two authors agree on the curriculum. The reason the third move matters more than it used to is the subject of the last section of this chapter: a reason you can write down is a reason you can hand to someone, or something, else.