Easing is the invisible difference between an animation that feels expensive and one that feels cheap. You can ship the same 12-point component with the same layout, the same typography, the same interaction logic — change the easing curve and suddenly it feels like a premium product or a hobby project. Linear motion (constant velocity from A to B) is not natural. Human motion, physics, organic form — everything in the natural world accelerates and decelerates. Your animations should too.
Most developers set `transition: 300ms ease-in-out` and ship. That's the browser's default cubic-bezier, which is a compromise curve designed to be "safe" for everything — good at nothing. Aidxn doesn't do compromise. We ship out-quart for entry animations (feels expensive, hits the target fast then eases into place), in-out-cubic for page transitions (slow-start slow-end, choreographs with other elements), and custom bezier curves for hero sequences where motion is storytelling. This is what separates a Stripe-grade marketing site from a Wix template.
Why Easing Matters
Easing is a curve that describes acceleration and deceleration over time. The browser's timing functions (`ease`, `ease-in-out`, `linear`, etc.) are all cubic-bezier curves — equations that map time (0 to 1) to position (0 to 1). The shape of that curve determines how your animation feels.
Linear (0.0, 0.0, 1.0, 1.0) is a straight diagonal — constant velocity. Boring. Mechanical. Your eye detects it immediately as "not real motion." Use linear only for rotating progress spinners or repeating background patterns where you want uniform velocity.
ease-in starts slow, accelerates hard toward the end. Feels like something is launching. Good for elements leaving the viewport or dropping down the page.
ease-out starts fast, decelerates smoothly to rest. Feels like something is landing. Good for elements entering the viewport or settling into place. Most of your animations should be ease-out or out-quart.
ease-in-out is slow-fast-slow: ramp up, cruise, ramp down. It's the browser default. It works, but it's generic. Too much ramp-up time for quick interactions. Too much deceleration for a snappy feel.
Aidxn's standard: out-quart (cubic-bezier value: `0.165, 0.84, 0.44, 1`) for 80% of your animations. It's what Stripe, Vercel, and Framer use. Fast start, aggressive slowdown at the end. Feels premium. Feels intentional. Feels shipped by a team that cares about motion.
Five Essential Curves With Bezier Values
1. Out-Quart (Entry / Element Appearance)
Cubic-bezier: `0.165, 0.84, 0.44, 1`
Fast start, smooth deceleration. Elements appear and settle immediately. This is the premium default. Use for:
- Modals sliding in
- Cards fading in on page load
- Buttons scaling on hover
- Dropdowns appearing
At 300ms, an element animates in and feels present immediately. No overshooting, no sluggish settle time. This is why Stripe's CTA buttons feel expensive.
2. In-Out-Cubic (Page Transitions / Connected Motion)
Cubic-bezier: `0.645, 0.045, 0.355, 1`
Slow start, fast middle, slow end. When multiple elements are animating in sequence, in-out-cubic choreographs them together. A card waits, then accelerates, then settles. Feels like coordinated motion, not random.
- Staggered grid animations (each card uses in-out-cubic with a delay)
- Page transition overlays fading in/out
- Hero section animations that need rhythm
The slow-start makes the motion feel intentional (not accidental). The slow-end gives your eye time to register the final state. Pair with 250–350ms and stagger children by 30–50ms for professional effect.
3. Out-Expo (Fast, Dramatic Entry)
Cubic-bezier: `0.19, 1, 0.22, 1`
Extremely fast start, very quick settle. This is the "punch" curve — used sparingly on hero animations or high-impact CTAs. Too much eases and it looks hyperactive. 150–200ms is the sweet spot.
- Hero headline scaling in
- High-emphasis CTA button entrance
- Cursor-follow effects on demand
Use once per page, max. It's loud. It's meant to draw attention.
4. In-Cubic (Slow, Controlled Exit)
Cubic-bezier: `0.55, 0.055, 0.675, 0.19`
Fast at first, slows into deceleration. Opposite of ease-out. Elements feel like they're decelerating under gravity. Use for dismissals, slides out, fades to nothing.
- Modal closing (exit from bottom)
- Sidebar collapsing
- Toast notifications sliding away
Psychologically, it feels heavy. Feels final. Pair with 200–250ms.
5. Out-Cubic (Smooth, Natural Ease)
Cubic-bezier: `0.215, 0.61, 0.355, 1`
Faster than ease-out, less aggressive than out-quart. The "goldilocks" curve. Fast enough to feel responsive, smooth enough to look natural. If you're not sure which curve to use, try out-cubic.
- Scroll-triggered fade-ins
- Opacity transitions
- Transform scaling (e.g., thumbnail → fullscreen)
Works at any duration. 200–400ms default. It's rarely the wrong choice.
Framer Motion Syntax
Define your easing curves at the top of your component file, then use them in variants:
import { motion } from 'framer-motion';
const easing = {
outQuart: [0.165, 0.84, 0.44, 1],
inOutCubic: [0.645, 0.045, 0.355, 1],
outExpo: [0.19, 1, 0.22, 1],
inCubic: [0.55, 0.055, 0.675, 0.19],
outCubic: [0.215, 0.61, 0.355, 1],
};
const cardVariants = {
hidden: { opacity: 0, y: 20 },
visible: (i: number) => ({
opacity: 1,
y: 0,
transition: {
delay: i * 0.05,
duration: 0.3,
ease: easing.outQuart,
},
}),
};
export const CardGrid = ({ items }) => {
return (
<motion.div
className="grid grid-cols-3 gap-4"
initial="hidden"
animate="visible"
>
{items.map((item, i) => (
<motion.div
key={item.id}
custom={i}
variants={cardVariants}
className="p-4 border rounded"
>
{item.title}
</motion.div>
))}
</motion.div>
);
};
Pass the easing array directly to the `ease` property. Framer accepts cubic-bezier as an array of 4 numbers. That's it. Each card staggered by 50ms, each card using out-quart easing. Premium feel. Ship it.
GSAP Syntax
GSAP uses a different naming convention, but you can still define custom bezier curves:
import gsap from 'gsap';
// Use built-in easing
gsap.to('#element', {
duration: 0.3,
opacity: 1,
y: 0,
ease: 'power4.out', // out-quart equivalent
});
// Custom cubic-bezier
gsap.to('#element', {
duration: 0.3,
opacity: 1,
ease: 'cubic-bezier(0.165, 0.84, 0.44, 1)', // out-quart
});
// Staggered timeline with easing
const timeline = gsap.timeline();
gsap.utils.toArray('.card').forEach((card, i) => {
timeline.to(
card,
{
opacity: 1,
y: 0,
duration: 0.3,
ease: 'power3.out', // out-cubic
},
i * 0.05 // stagger
);
});
GSAP's `power4.out` is equivalent to out-quart. `power3.out` is out-cubic. `power2.inOut` is in-out-quad. For exact bezier control, use the `cubic-bezier()` notation directly. Both work. GSAP will parse it.
Aidxn Defaults: Timing Table
| Animation Type | Duration | Easing |
|---|---|---|
| Button hover scale | 150ms | out-quart |
| Modal entry | 250ms | out-quart |
| Card fade-in (grid) | 300ms | in-out-cubic |
| Page transition overlay | 200ms | out-cubic |
| Hero headline scale | 150ms | out-expo |
| Modal dismiss | 200ms | in-cubic |
| Scroll-triggered fade | 400ms | out-cubic |
| Sidebar collapse | 250ms | in-cubic |
These are the Aidxn baselines. Everything ships at 150ms minimum (anything slower feels sluggish), 400ms maximum (anything slower feels waiting-room). Most interactions live in the 200–300ms band. Stagger children by 30–50ms. The math compounds fast: 12 cards × 50ms stagger = 600ms total animation (snappy, not slow).
Mobile Considerations
Mobile devices have lower refresh rates (some older phones still run 60hz, not 120hz). Easing curves still apply, but timings matter more.
Rule: On mobile, keep entry animations ≤250ms. Dismissals ≤200ms. The lower processing power means longer animations can stutter. Test on real devices. Chrome DevTools' device emulation doesn't capture the real physics of a mid-range Android phone.
Stagger animations the same way. It makes the sequence feel cohesive across devices. A card entering at 300ms with out-quart easing looks professional on both 60hz and 120hz screens.
Six FAQs
Can I use `ease: true` in Framer instead of cubic-bezier?
Yes, but don't. `ease: true` defaults to ease-in-out, which is generic. Always specify your curve. It's 30 characters of code difference and it's the difference between cheap and expensive feel.
What if I want a custom easing curve that's not cubic-bezier?
Use a cubic-bezier approximation. Most natural easing can be approximated with a 4-point cubic curve. For truly custom (5+ point) curves, use GSAP's CustomEase plugin. But honestly, the 5 curves in this post cover 95% of real work.
Does easing affect performance?
No. Easing is just math applied to the animation values. Whether the motion follows linear or out-quart, the browser is still pushing the same number of frames to the GPU. Easing cost: essentially zero.
What if an animation feels off but I don't know which curve to try?
Start with out-quart for everything. If it feels too snappy, try out-cubic (slightly gentler). If it needs more choreography (multiple elements), use in-out-cubic. If it's leaving the viewport, flip to in-cubic. The defaults cover 90% of problems.
Should I animate color with the same easing as transform?
Yes. All properties on an element should share the same easing curve and duration. If you're animating both `background-color` and `transform: scale()`, use the same easing on both. It keeps the motion cohesive.
How do I know if my easing is working?
Slow down your browser in DevTools (Performance tab → slow motion) and watch frame by frame. You should see the animation accelerating hard at the start (if out-quart), then settling smoothly. If it looks linear at any speed, your easing didn't apply correctly — check your syntax.
The Bottom Line
Linear easing is the hobbyist tell. Every element moves at constant velocity, no acceleration, no deceleration. Premium sites ship cubic-bezier curves: out-quart for 80% of your animations (fast start, smooth settle), in-out-cubic for choreography (slow-start slow-end rhythm), out-cubic for general-purpose ease (the goldilocks curve), and in-cubic for dismissals. Duration: 150–300ms for entry, 200–250ms for exit, 400ms max for scroll-triggered fades. Stagger children by 30–50ms. Test on mobile. That's the difference between a site that feels shipped and a site that feels thrown together. For real-world patterns on scroll-driven hero sequences, check out our work on Framer Motion vs GSAP.