Skip to content

Web Development

Animation Easing Curves — The Detail That Separates Premium From Hobbyist

Linear easing is a tells. Every hobbyist site moves every object in a straight line, constant speed. Premium sites sculpt motion with cubic-bezier curves: out-quart for entry animations (snappy start, gentle settle), in-out-cubic for section transitions (slow-start, slow-end rhythm), custom curves for hero sequences. Here's the math, the syntax, the Aidxn defaults, and why sub-300ms timing is the baseline.

📈

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.

Let us make some quick suggestions?
Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.