Bài 26.1: CSS transitions và animations

Bài 26.1: CSS transitions và animations
Trong thế giới web hiện đại, một giao diện người dùng chỉ hoạt động là chưa đủ. Chúng ta cần một giao diện sống động, phản hồi nhanh và tạo ấn tượng khó quên. Và đó chính là lúc CSS Transitions và CSS Animations tỏa sáng! Chúng là những công cụ mạnh mẽ giúp bạn biến các thay đổi trạng thái tĩnh lặng thành những chuyển động mượt mà, thu hút và nâng cao trải nghiệm người dùng (UX) một cách đáng kể.
Bài viết này sẽ đưa bạn đi sâu vào thế giới đầy màu sắc của chuyển động trên web chỉ với CSS, từ những thay đổi trạng thái đơn giản đến các chuỗi hiệu ứng phức tạp.
CSS Transitions: Cầu Nối Mượt Mà Giữa Các Trạng Thái
Hãy tưởng tượng bạn muốn một nút bấm thay đổi màu nền khi người dùng di chuột qua. Thay vì nó "nhảy" đột ngột sang màu mới, CSS Transitions cho phép bạn định nghĩa cách thay đổi đó diễn ra dần dần trong một khoảng thời gian nhất định. Đây là cách tạo ra những hiệu ứng mượt mà, không giật cục khi thuộc tính CSS của một phần tử thay đổi giá trị.
Transition chỉ xảy ra khi có sự thay đổi về giá trị của một thuộc tính CSS nào đó, ví dụ như khi phần tử được hover, focus, hoặc khi một class CSS được thêm/bớt bằng JavaScript.
Để sử dụng transition, bạn cần xác định ít nhất hai điều:
- Thuộc tính nào sẽ được chuyển động?
- Thời gian chuyển động là bao lâu?
Chúng ta có các thuộc tính CSS chính để điều khiển transitions:
transition-property
: Chỉ định tên (hoặc danh sách tên) của các thuộc tính CSS mà bạn muốn áp dụng hiệu ứng transition khi chúng thay đổi. Giá trị phổ biến nhất làall
để áp dụng cho tất cả các thuộc tính có thể chuyển động.transition-duration
: Xác định thời gian (tính bằng giây -s
hoặc mili giây -ms
) để hoàn thành hiệu ứng transition. Đây là thuộc tính bắt buộc để transition hoạt động.transition-timing-function
: Định nghĩa tốc độ chuyển động trong suốt thời gian diễn ra transition (đường cong gia tốc). Các giá trị thông dụng bao gồm:ease
: Bắt đầu chậm, tăng tốc ở giữa, kết thúc chậm (mặc định).linear
: Tốc độ không đổi từ đầu đến cuối.ease-in
: Bắt đầu chậm.ease-out
: Kết thúc chậm.ease-in-out
: Bắt đầu và kết thúc chậm.cubic-bezier(n,n,n,n)
: Cho phép bạn tạo đường cong tốc độ tùy chỉnh.
transition-delay
: Xác định thời gian chờ (tính bằng giây hoặc mili giây) trước khi hiệu ứng transition bắt đầu.
Ví dụ về Transition
Hãy tạo một khối đơn giản thay đổi kích thước và màu sắc khi hover:
HTML:
<div class="box"></div>
CSS:
.box {
width: 100px;
height: 100px;
background-color: blue;
margin: 50px; /* Just for spacing */
/* Định nghĩa transition */
transition-property: width, background-color; /* Áp dụng cho width và background-color */
transition-duration: 0.5s; /* Kéo dài 0.5 giây */
transition-timing-function: ease-in-out; /* Chuyển động mượt mà ở đầu và cuối */
/* transition-delay: 0.2s; /* Uncomment để thêm độ trễ 0.2s trước khi bắt đầu */
}
.box:hover {
width: 200px; /* Thay đổi width khi hover */
background-color: red; /* Thay đổi màu khi hover */
}
Giải thích:
Khi bạn di chuột qua phần tử div
có class box
, các thuộc tính width
và background-color
của nó sẽ thay đổi từ giá trị ban đầu sang giá trị được định nghĩa trong :hover
. Nhờ các thuộc tính transition-*
, sự thay đổi này không diễn ra ngay lập tức mà diễn ra một cách mượt mà trong vòng 0.5 giây, với tốc độ được điều khiển bởi hàm ease-in-out
.
Sử Dụng Shorthand transition
Thay vì viết từng thuộc tính transition-*
riêng lẻ, bạn có thể sử dụng thuộc tính transition
viết tắt. Cú pháp phổ biến nhất là:
transition: [property] [duration] [timing-function] [delay];
Bạn có thể liệt kê nhiều transition cho các thuộc tính khác nhau, phân cách bởi dấu phẩy.
CSS (Sử dụng Shorthand):
.box {
width: 100px;
height: 100px;
background-color: blue;
margin: 50px;
/* Sử dụng shorthand transition */
transition: width 0.5s ease-in-out, background-color 0.5s ease-in-out;
/* Hoặc đơn giản hơn nếu áp dụng cho tất cả các thuộc tính có thể transition */
/* transition: all 0.5s ease-in-out; */
}
.box:hover {
width: 200px;
background-color: red;
}
Shothand giúp code ngắn gọn và dễ đọc hơn khi bạn đã quen với thứ tự các giá trị.
CSS Animations: Tạo Nên Những Câu Chuyện Chuyển Động
Trong khi transitions chỉ là "cây cầu" giữa hai trạng thái, CSS Animations mạnh mẽ hơn nhiều. Chúng cho phép bạn định nghĩa một chuỗi các "điểm dừng" (keyframes) và cách phần tử sẽ di chuyển, thay đổi giữa các điểm dừng đó theo thời gian. Animations có thể tự chạy ngay khi phần tử xuất hiện, lặp lại vô hạn, hoặc được điều khiển phức tạp hơn.
Để tạo một animation, bạn cần hai phần chính:
- Định nghĩa
@keyframes
: Nơi bạn "kể" câu chuyện chuyển động, xác định các điểm dừng và thuộc tính của phần tử tại mỗi điểm đó. - Áp dụng animation cho phần tử: Sử dụng các thuộc tính
animation-*
để gắn@keyframes
đã định nghĩa vào phần tử và điều khiển cách nó chạy.
Định Nghĩa @keyframes
Cú pháp cơ bản của @keyframes
như sau:
@keyframes ten-animation-cua-ban {
0% { /* Thuộc tính CSS tại thời điểm bắt đầu (0%) */
/* Ví dụ: opacity: 0; */
}
50% { /* Thuộc tính CSS tại thời điểm giữa (50%) */
/* Ví dụ: transform: translateY(-20px); */
}
100% { /* Thuộc tính CSS tại thời điểm kết thúc (100%) */
/* Ví dụ: opacity: 1; */
}
}
Bạn có thể sử dụng từ khóa from
(tương đương 0%) và to
(tương đương 100%) cho các animation đơn giản chỉ có điểm bắt đầu và kết thúc.
Ví dụ @keyframes
:
@keyframes fadeAndMove {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0% {
transform: scale(1); /* Kích thước ban đầu */
}
50% {
transform: scale(1.1); /* Phóng to 10% */
}
100% {
transform: scale(1); /* Trở về kích thước ban đầu */
}
}
Áp Dụng Animation
Sau khi định nghĩa @keyframes
, bạn sử dụng các thuộc tính animation-*
để áp dụng nó cho một phần tử:
animation-name
: Tên của@keyframes
bạn muốn áp dụng (ví dụ:fadeAndMove
). Đây là thuộc tính bắt buộc.animation-duration
: Thời gian (giây hoặc mili giây) để hoàn thành một chu kỳ của animation. Đây cũng là thuộc tính bắt buộc.animation-timing-function
: Đường cong tốc độ cho animation (tương tự transition).animation-delay
: Thời gian chờ trước khi animation bắt đầu.animation-iteration-count
: Số lần animation lặp lại. Có thể là một số cụ thể (1
,2
,3
,...) hoặcinfinite
để lặp vô hạn.animation-direction
: Hướng chạy của animation. Các giá trị phổ biến:normal
(từ 0% đến 100%),reverse
(từ 100% về 0%),alternate
(lần lượt normal rồi reverse),alternate-reverse
.animation-fill-mode
: Xác định trạng thái của phần tử trước khi animation bắt đầu và sau khi kết thúc.none
(mặc định): Phần tử trở về trạng thái CSS ban đầu sau khi animation kết thúc.forwards
: Phần tử giữ nguyên trạng thái của keyframe cuối cùng (thường là 100% hoặcto
).backwards
: Phần tử áp dụng trạng thái của keyframe đầu tiên (0% hoặcfrom
) trong thời giananimation-delay
.both
: Kết hợp cảforwards
vàbackwards
.
animation-play-state
: Điều khiển trạng thái chạy của animation:running
(mặc định) hoặcpaused
. Thường dùng kết hợp với pseudo-class:hover
hoặc JavaScript.
Ví dụ về Animation
Sử dụng các @keyframes
đã định nghĩa ở trên:
HTML:
<div class="animated-element">Chào mừng!</div>
<div class="pulse-button">Nhấn đây!</div>
CSS:
/* Định nghĩa keyframes */
@keyframes fadeAndMove {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
/* Áp dụng animation */
.animated-element {
font-size: 24px;
color: #333;
opacity: 0; /* Đảm bảo phần tử ẩn lúc đầu nếu dùng fade-in */
margin: 20px;
animation-name: fadeAndMove; /* Tên keyframes */
animation-duration: 1s; /* Thời gian 1 chu kỳ */
animation-timing-function: ease-out; /* Đường cong tốc độ */
animation-delay: 0.5s; /* Chờ 0.5s rồi chạy */
animation-iteration-count: 1; /* Chạy 1 lần */
animation-fill-mode: forwards; /* Giữ trạng thái cuối cùng */
}
.pulse-button {
display: inline-block; /* Để transform scale hoạt động tốt hơn */
padding: 10px 20px;
background-color: hotpink;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 20px;
animation-name: pulse; /* Tên keyframes */
animation-duration: 1.5s; /* Thời gian 1 chu kỳ */
animation-timing-function: ease-in-out;
animation-iteration-count: infinite; /* Lặp vô hạn */
animation-direction: alternate; /* Chạy xuôi rồi ngược */
}
Giải thích:
- Phần tử
.animated-element
sẽ xuất hiện mượt mà từ dưới lên sau 0.5 giây, hoàn thành hiệu ứng trong 1 giây. Doanimation-fill-mode: forwards;
và trạng thái cuối cùng cóopacity: 1
, phần tử sẽ hiển thị rõ ràng sau khi animation kết thúc. - Phần tử
.pulse-button
sẽ liên tục "nhịp đập" (phóng to rồi thu nhỏ) vô hạn.animation-iteration-count: infinite
vàanimation-direction: alternate
tạo ra hiệu ứng lặp đi lặp lại nhịp nhàng này.
Sử Dụng Shorthand animation
Tương tự transition, animation cũng có thuộc tính viết tắt:
animation: [name] [duration] [timing-function] [delay] [iteration-count] [direction] [fill-mode] [play-state];
Thứ tự các giá trị rất quan trọng! Thường thì duration
và delay
có thể gây nhầm lẫn nếu bạn có cả hai; giá trị đầu tiên có đơn vị thời gian (s
hoặc ms
) sẽ được coi là duration
, giá trị thứ hai là delay
.
CSS (Sử dụng Shorthand):
/* Định nghĩa keyframes vẫn giữ nguyên */
@keyframes fadeAndMove { /* ... */ }
@keyframes pulse { /* ... */ }
/* Áp dụng animation với shorthand */
.animated-element {
/* ... other styles ... */
animation: fadeAndMove 1s ease-out 0.5s 1 forwards; /* name duration timing delay iteration-count fill-mode */
}
.pulse-button {
/* ... other styles ... */
animation: pulse 1.5s ease-in-out infinite alternate; /* name duration timing iteration-count direction */
/* Lưu ý: delay và fill-mode không được chỉ định ở đây sẽ nhận giá trị mặc định */
}
Shothand animation
rất phổ biến vì tính gọn lẹ của nó.
Transitions Hay Animations? Khi Nào Sử Dụng Cái Nào?
Việc lựa chọn giữa transition và animation phụ thuộc vào yêu cầu của hiệu ứng:
- Sử dụng Transitions khi bạn muốn tạo hiệu ứng mượt mà cho sự thay đổi giữa hai trạng thái (ví dụ: trạng thái bình thường và trạng thái hover/focus/active, hoặc trạng thái trước và sau khi thêm/bớt class). Transition luôn cần một sự kiện kích hoạt để thay đổi thuộc tính.
- Sử dụng Animations khi bạn cần tạo các hiệu ứng phức tạp hơn, có nhiều hơn hai "điểm dừng", lặp lại tự động, hoặc cần kiểm soát chi tiết hơn về dòng thời gian của hiệu ứng. Animation có thể tự chạy ngay khi phần tử xuất hiện trên trang mà không cần tương tác của người dùng.
Các Vấn Đề Cần Quan Tâm
- Hiệu suất (Performance): Animation/transition có thể tốn tài nguyên, đặc biệt là trên thiết bị di động hoặc với các hiệu ứng phức tạp. Cố gắng animate các thuộc tính như
opacity
vàtransform
thay vìwidth
,height
,margin
,padding
,top
,left
, v.v., vìopacity
vàtransform
thường được tăng tốc phần cứng bởi trình duyệt. - Tương thích trình duyệt: Hầu hết các trình duyệt hiện đại đều hỗ trợ tốt CSS Transitions và Animations. Tuy nhiên, với các phiên bản cũ hơn, bạn có thể cần sử dụng tiền tố nhà cung cấp (vendor prefixes) như
-webkit-
,-moz-
,-o-
. Ngày nay, điều này ít phổ biến hơn nhờ các công cụ build tự động thêm tiền tố (như Autoprefixer). - Khả năng tiếp cận (Accessibility): Một số người dùng có thể bị chóng mặt hoặc khó chịu với các hiệu ứng chuyển động quá nhanh hoặc liên tục. Hãy cân nhắc cung cấp tùy chọn cho người dùng để tắt hoặc giảm bớt hiệu ứng (ví dụ: sử dụng media query
@media (prefers-reduced-motion: reduce) { /* ... */ }
). - Công cụ phát triển (Developer Tools): Trình duyệt có các công cụ tuyệt vời để kiểm tra và debug transitions/animations, cho phép bạn xem dòng thời gian, tốc độ và các thuộc tính đang thay đổi. Hãy tận dụng chúng!
Comments