Giao Diện Sống Động Với Framer Motion

Hướng dẫn từng bước thêm các tương tác vi mô (microinteractions) dạng lò xo vào component để ứng dụng của bạn cho cảm giác cao cấp và phản hồi tốt hơn.

14/05/2026
15 phút đọc

Trong thế giới Frontend hiện đại, một website "chạy được" thôi chưa đủ. Khách hàng và người dùng ngày càng khó tính, họ đòi hỏi một website phải "sống động", có hồn và tạo ra cảm giác cao cấp (Premium UX). Khác biệt giữa một website rẻ tiền và một website tiền tỷ nhiều khi nằm ở những chuyển động cực kỳ nhỏ bé - được gọi là Microinteractions.

Và để làm chủ được nghệ thuật Animation trong React, không có thư viện nào mạnh mẽ, dễ dùng và "đỉnh" hơn Framer Motion. Hôm nay chúng ta sẽ mổ xẻ thư viện này từ cơ bản đến nâng cao nhé.

1

Microinteractions Là Gì? Tại Sao Quan Trọng?

Microinteractions (Tương tác vi mô) là những phản hồi vật lý hoặc hình ảnh rất nhỏ khi người dùng thực hiện một thao tác trên UI. Ví dụ:

  • Khi bạn rà chuột qua nút "Submit", nút đó hơi phình to ra và sáng lên.
  • Khi bạn bấm Like, trái tim nảy bật lên như lò xo.
  • Khi đóng một Modal, nó không biến mất lập tức mà trượt nhẹ xuống và mờ dần.
Tâm lý học UX:

Mắt người rất nhạy cảm với chuyển động. Những chuyển động mượt mà (có tính vật lý) mang lại cho người dùng cảm giác "ứng dụng này đang phản hồi lại tôi", tạo ra sự tin tưởng và cảm giác thao tác trơn tru, cao cấp.

2

Cài Đặt Framer Motion

Cài đặt thư viện vào dự án React hoặc Next.js của bạn cực kỳ đơn giản:

npm install framer-motion
# hoặc
yarn add framer-motion
# hoặc
pnpm add framer-motion

Lưu ý quan trọng cho Next.js App Router: Framer Motion thao tác trực tiếp vào DOM và Event Listeners, nên mọi component sử dụng Framer Motion bắt buộc phải là Client Component (phải có "use client"; ở đầu file).

3

Nguyên Lý Cơ Bản (The Core)

Để tạo animation, bạn không dùng thẻ HTML thông thường như <div> hay <button>, mà bạn phải sử dụng đối tượng motion từ thư viện: <motion.div>, <motion.button>.

Có 3 thuộc tính chính (Props) mà bạn cần thuộc lòng:

  • initial: Trạng thái bắt đầu (trước khi animation chạy).
  • animate: Trạng thái kết thúc mong muốn (Framer Motion sẽ tự động nội suy đường đi từ initial đến animate).
  • transition: Quản lý cách thức di chuyển (nhanh/chậm, độ nảy, delay...).
import { motion } from "framer-motion";

export function SimpleBox() {
  return (
    <motion.div
      initial={{ opacity: 0, y: 50 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.5 }}
      className="w-32 h-32 bg-indigo-500 rounded-xl"
    />
  );
}

Đoạn code trên sẽ tạo ra một chiếc hộp xuất hiện từ dưới lên (y: 50 -> 0) và mờ dần rõ lên (opacity: 0 -> 1) trong vòng 0.5 giây.

4

Bí Mật Của Lò Xo (Spring Physics)

Đừng bao giờ dùng hiệu ứng linear hay ease thông thường cho các thao tác của người dùng. Bí mật của các App như iOS hay Telegram nằm ở Vật lý lò xo (Spring Physics).

Framer Motion mặc định sử dụng type: "spring" cho các di chuyển không gian. Hãy điều chỉnh 2 thông số: stiffness (Độ cứng lò xo - tốc độ) và damping (Độ hãm - độ nảy).

<motion.div
  initial={{ x: -200 }}
  animate={{ x: 0 }}
  transition={{
    type: "spring",
    stiffness: 260, // Lò xo càng cứng, bung càng nhanh
    damping: 20     // Độ hãm càng nhỏ, nảy càng nhiều
  }}
/>

Hiệu ứng Spring tạo ra sự "chân thực" vì nó bắt chước định luật vật lý của thế giới thực. Component khi dừng lại sẽ không dừng khựng lại cứng nhắc mà sẽ hơi nảy dội lại một chút.

5

Hover, Tap & Gestures

Framer Motion cung cấp các thuộc tính gắn trực tiếp để xử lý tương tác của người dùng cực nhàn rỗi (không cần viết CSS :hover hay :active):

<motion.button
  whileHover={{ scale: 1.05, backgroundColor: "#4f46e5" }}
  whileTap={{ scale: 0.95 }}
  className="px-6 py-2 bg-indigo-600 text-white rounded-lg"
>
  Click Me!
</motion.button>

Thậm chí nó có cả drag để bạn làm tính năng kéo thả (Kéo tinder card, sắp xếp list, ...)

<motion.div
  drag
  dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }} // Kéo thả nhưng tự dội về vị trí cũ (Snap)
/>
6

Phép Thuật Layout Animations

Đây là tính năng đáng tiền nhất của Framer Motion. Khi bạn thêm thuộc tính layout vào một element, Framer Motion sẽ theo dõi sự thay đổi vị trí/kích thước của element đó trên DOM và tự động thực hiện animation chuyển tiếp cực mượt.

Ví dụ: Khi bạn có một Grid danh sách bài viết, bạn filter (lọc) bài viết. Một số phần tử bị xóa đi, các phần tử còn lại sẽ lập tức bị dồn lên trên. Nếu không có Animation, nó giật cục rất xấu. Chỉ cần thêm layout:

<motion.div layout className="card">
  <h3>Bài viết</h3>
</motion.div>

Tự dưng các bài viết sẽ "trượt" nhẹ nhàng vào chỗ trống mới thay vì nhảy cái rụp. Phép thuật!

7

AnimatePresence (Mount/Unmount)

Trong React, khi một component bị Unmount (Bị xóa khỏi DOM bằng {isOpen && <Modal />}), nó biến mất lập tức. Làm sao để bắt nó chạy Animation mờ dần rồi mới bị xóa đi?

Đó là lúc cần AnimatePresence. Bọc các phần tử cần Unmount bằng component này, và thêm thuộc tính exit vào motion.div:

import { motion, AnimatePresence } from "framer-motion";

function App() {
  const [isOpen, setIsOpen] = useState(true);

  return (
    <AnimatePresence>
      {isOpen && (
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: -20 }} // Sẽ chạy cái này trước khi Unmount
        >
          Tôi là Modal!
        </motion.div>
      )}
    </AnimatePresence>
  );
}
8

Scroll Animations (Hiệu ứng cuộn)

Muốn các phần tử tự động hiện ra khi người dùng cuộn (scroll) trang web xuống tới nó? Vô cùng đơn giản với whileInView:

<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }} // Chỉ chạy 1 lần, chạy khi cuộn cách 100px
>
  Nội dung xuất hiện khi cuộn tới...
</motion.div>
9

Tối Ưu Hiệu Năng

Framer Motion rất nhanh vì nó thao tác trực tiếp bằng Web Animations API. Tuy nhiên, để đảm bảo 60fps trên điện thoại yếu, hãy ghi nhớ 1 nguyên tắc vàng:

Tuyệt đối không animate các thuộc tính đắt đỏ!

Chỉ được phép Animate transform (translate, scale, rotate) và opacity. Những thuộc tính này được xử lý bởi GPU phần cứng.

Tránh xa việc Animate width, height, top, left, box-shadow vì nó bắt trình duyệt phải tính toán lại (Reflow/Repaint) Layout, gây giật lag nặng.

Hy vọng qua bài viết siêu dài và đầy đủ này, bạn đã tự tin làm chủ được Framer Motion và hô biến mọi UI/UX trở thành những tác phẩm nghệ thuật mượt mà. Hẹn gặp lại!

Bài viết liên quan

Bí Quyết Xây Dựng Bento Grid Hoàn Hảo Bằng CSS Grid

Cách sử dụng grid-template-columns và grid-auto-flow để tạo ra layout tạp chí hiện đại bất đối xứng.

14/05/2026
10 phút đọc

Thiết Kế Giao Diện Cùng Tailwind v4 & Hệ Màu OKLCH

Khám phá cách hệ màu OKLCH mới trong Tailwind v4 cho phép tạo màu sắc đồng đều về cảm nhận thị giác, mang lại thiết kế UI rực rỡ và dễ tiếp cận hơn so với RGB/HSL truyền thống.

14/05/2026
8 phút đọc

Giải Mã React Server Components

Bối rối với RSC? Chúng tôi sẽ bóc tách mô hình tư duy, chỉ rõ khi nào cần dùng 'use client', và cách fetch dữ liệu hiệu quả trên môi trường edge.

14/05/2026
15 phút đọc

Micro Frontends Module Federation Với Vite

Chia nhỏ ứng dụng khổng lồ thành các micro frontend độc lập với tốc độ build chớp nhoáng của Vite.

14/05/2026
12 phút đọc