Tạo CSS animation: keyframes, bảy thuộc tính điều khiển và cách viết gộp cho đúng
Công cụ dựng sẵn tám hiệu ứng keyframes thường dùng, cho bạn chỉnh thời lượng, đường cong tốc độ, độ trễ, số lần lặp, chiều chạy và chế độ giữ trạng thái, rồi xuất ra cả dạng viết đầy đủ lẫn dạng viết gộp. Khối xem trước chạy ngay theo thiết lập, có nút tạm dừng để bạn quan sát từng pha của chuyển động.
Tính năng nổi bật
- Tám hiệu ứng dựng sẵn: hiện dần, mờ dần, trượt từ trái, trượt từ phải, nảy, xoay, phóng to thu nhỏ và nhấp nháy
- Đặt tên keyframes theo ý bạn, tên này đi thẳng vào mã xuất ra
- Chỉnh thời lượng theo giây với bước nhảy 0,1 và giá trị nhỏ nhất 0,1 giây
- Năm đường cong tốc độ: ease, linear, ease-in, ease-out và ease-in-out
- Chỉnh độ trễ, chọn số lần lặp gồm 1, 2, 3, 5 hoặc chạy vô hạn
- Bốn chiều chạy và bốn chế độ giữ trạng thái để thử nhanh từng tổ hợp
- Khối xem trước chạy đúng thiết lập, kèm nút tạm dừng và chạy lại
- Mã xuất ra có cả khối keyframes, dạng viết đầy đủ từng thuộc tính và dạng viết gộp một dòng
Vì sao nên thử chuyển động bằng công cụ trước khi viết vào dự án
Chuyển động là thứ đọc mã không hình dung nổi. Cùng một hiệu ứng nảy, chạy trong 0,3 giây thì gọn gàng, chạy trong 1,5 giây thì trông chậm chạp và gây khó chịu khi người dùng phải đợi. Đường cong tốc độ còn khó đoán hơn: ease và ease-in-out nghe gần giống nhau nhưng đặt cạnh nhau trên cùng một khối vuông thì khác biệt rất rõ. Nếu bạn chỉnh trực tiếp trong dự án, mỗi lần đổi một giá trị là một vòng lưu tệp, chờ tải lại, rồi phải kích hoạt lại đúng trạng thái mới thấy chuyển động chạy. Ở đây bảy ô điều khiển nằm cạnh khối xem trước đang chạy liên tục, nên bạn so sánh được ngay. Ngoài ra mã xuất ra viết cả hai dạng, đầy đủ và gộp, nên đây cũng là cách nhanh để kiểm chứng thứ tự giá trị trong dạng gộp mà nhiều người viết sai.
Lợi ích khi sử dụng
- So sánh trực tiếp năm đường cong tốc độ trên cùng một khối
- Thấy ngay khác biệt giữa bốn chế độ giữ trạng thái mà không phải đọc tài liệu
- Có sẵn cả dạng viết đầy đủ để dễ đọc và dạng viết gộp để dán nhanh
- Nút tạm dừng giúp soi từng pha thay vì nhìn chuyển động chạy liên tục
- Toàn bộ chạy trong trình duyệt, không cần cài gói phụ thuộc nào
Cách tạo một chuyển động và lấy mã
- 1Chọn một trong tám hiệu ứng dựng sẵn để lấy khối keyframes làm điểm khởi đầu.
- 2Đặt tên cho chuyển động, nên chọn tên mô tả đúng việc nó làm vì tên keyframes có phạm vi toàn cục.
- 3Chỉnh thời lượng và đường cong tốc độ, quan sát khối xem trước cho tới khi nhịp chạy đúng ý.
- 4Đặt độ trễ, số lần lặp, chiều chạy và chế độ giữ trạng thái, mỗi lần đổi một giá trị để thấy rõ tác động.
- 5Bấm sao chép, dán khối keyframes cùng phần khai báo vào tệp CSS rồi gắn lớp vào phần tử cần chạy.
Bảy thuộc tính điều khiển và bẫy thứ tự trong dạng viết gộp
Một chuyển động CSS gồm khối keyframes mô tả các mốc trạng thái, và nhóm thuộc tính điều khiển cách chạy khối đó. Bảy thuộc tính công cụ này xuất ra lần lượt là animation-name để trỏ tới khối keyframes, animation-duration là thời lượng một vòng, animation-timing-function là đường cong tốc độ, animation-delay là độ trễ trước khi bắt đầu, animation-iteration-count là số vòng, animation-direction là chiều chạy, animation-fill-mode là trạng thái giữ lại ngoài thời gian chạy. Còn một thuộc tính thứ tám không nằm trong công cụ là animation-play-state, nhận giá trị running hoặc paused, rất tiện để dừng chuyển động khi người dùng rê chuột lên. Bẫy lớn nhất nằm ở dạng viết gộp: cả thời lượng và độ trễ đều là giá trị thời gian, và trình duyệt hiểu giá trị thời gian đầu tiên là thời lượng, giá trị thời gian thứ hai là độ trễ. Viết animation: fadeIn 2s ease 0.5s nghĩa là chạy 2 giây sau khi chờ nửa giây; đảo hai số là đảo luôn ý nghĩa. Đây là lỗi rất khó nhìn ra khi đọc lại mã.
Tám hiệu ứng dựng sẵn viết bằng keyframes như thế nào
Hiện dần đi từ opacity 0 ở mốc 0 phần trăm tới opacity 1 ở mốc 100 phần trăm, mờ dần thì ngược lại. Trượt từ trái đặt translateX âm 100 phần trăm ở mốc đầu rồi về 0, trượt từ phải đặt dương 100 phần trăm rồi về 0; lưu ý phần trăm ở đây tính theo kích thước của chính phần tử chứ không phải theo khung cha. Nảy dùng ba mốc: ở 0 và 100 phần trăm thì translateY bằng 0, ở 50 phần trăm thì lên âm 20 pixel, nên chuyển động đi lên rồi rơi về chỗ cũ. Xoay chạy rotate từ 0 độ tới 360 độ, đây là hiệu ứng hay dùng cho biểu tượng đang tải và thường đi kèm đường cong linear cùng số vòng vô hạn. Phóng to thu nhỏ dùng ba mốc với scale 1, 1,2 rồi về 1. Nhấp nháy đổi opacity từ 1 xuống 0,5 ở giữa rồi về 1. Khối keyframes trong công cụ là cố định, không sửa được trực tiếp; muốn thêm mốc hay đổi giá trị, bạn chép mã ra rồi sửa tay trong tệp CSS.
Chế độ giữ trạng thái và chiều chạy, hai thứ hay bị hiểu nhầm
Mặc định là none, nghĩa là ngoài khoảng thời gian chạy, phần tử quay về đúng kiểu dáng khai báo trong CSS thường. Hệ quả rất hay gặp: bạn làm hiệu ứng hiện dần cho một hộp, chạy xong hộp lại biến mất, vì mốc 0 phần trăm đặt opacity 0 nhưng CSS thường của hộp không đặt gì cả, và khi chuyển động kết thúc thì trạng thái cuối bị bỏ. Đặt forwards để giữ nguyên giá trị của mốc cuối sau khi chạy xong là cách xử lý đúng. Backwards thì áp giá trị của mốc đầu ngay trong khoảng chờ, dùng khi bạn có độ trễ và không muốn phần tử hiện ra ở trạng thái gốc rồi mới nhảy về trạng thái đầu. Both gộp cả hai. Về chiều chạy, normal chạy xuôi, reverse chạy ngược, alternate chạy xuôi vòng lẻ và ngược vòng chẵn, alternate-reverse thì đảo lại. Điều cần nhớ với alternate là số vòng chẵn sẽ kết thúc ở trạng thái ban đầu còn số vòng lẻ kết thúc ở trạng thái cuối, nên hai lần lặp và ba lần lặp cho ra kết quả cuối khác hẳn nhau.
Chỉ nên chạy chuyển động trên hai nhóm thuộc tính
Trình duyệt vẽ một khung hình qua ba giai đoạn: tính bố cục, tô màu, rồi ghép các lớp lại. Đổi width, height, top, left, margin hay padding buộc trình duyệt tính lại bố cục cho cả nhánh phần tử liên quan, mỗi khung hình một lần, và trên máy yếu là thấy giật ngay. Đổi màu nền hay bóng đổ thì bỏ được bước bố cục nhưng vẫn phải tô lại. Riêng transform và opacity có thể được xử lý ở bước ghép lớp, không cần tính bố cục cũng không cần tô lại, nên chạy mượt hơn hẳn. Vì vậy bốn trong tám hiệu ứng dựng sẵn ở đây dùng transform và ba hiệu ứng dùng opacity, đều nằm trong nhóm an toàn. Khi tự viết keyframes, hãy quy mọi chuyển động về hai thuộc tính này: muốn di chuyển thì dùng translate thay vì đổi left, muốn đổi kích thước thì dùng scale thay vì đổi width. Thuộc tính will-change có thể báo trước cho trình duyệt chuẩn bị lớp riêng, nhưng đừng rải nó khắp nơi vì mỗi lớp đều tốn bộ nhớ đồ họa.
Thời lượng hợp lý và tôn trọng lựa chọn giảm chuyển động
Với chuyển động phản hồi thao tác như nút đổi trạng thái hay bảng chọn mở ra, khoảng 150 tới 300 mili giây là vùng dễ chịu; dưới 100 mili giây người dùng gần như không kịp nhận ra, trên 500 mili giây bắt đầu có cảm giác giao diện chậm. Chuyển cảnh lớn hơn như hộp thoại trượt vào có thể lên 300 tới 500 mili giây. Riêng hiệu ứng chờ như vòng xoay tải thì thường một tới hai giây cho một vòng và chạy vô hạn. Một điểm bắt buộc phải làm mà nhiều dự án bỏ qua là hệ điều hành có tùy chọn giảm chuyển động dành cho người dễ chóng mặt hoặc nhạy cảm với chuyển động, và trình duyệt phơi lựa chọn đó ra qua truy vấn phương tiện prefers-reduced-motion. Hãy bọc các chuyển động lớn trong nhánh no-preference, hoặc thêm một nhánh reduce để rút thời lượng xuống mức không đáng kể. Điều này không làm giao diện xấu đi với người dùng thường, nhưng với một nhóm người dùng thì đó là khác biệt giữa dùng được và không dùng được.
Câu hỏi thường gặp (FAQ)
Trong dạng viết gộp, số nào là thời lượng và số nào là độ trễ?
Giá trị thời gian đầu tiên là thời lượng, giá trị thời gian thứ hai là độ trễ, không phụ thuộc vị trí các giá trị khác. Viết animation: fadeIn 2s ease 0.5s nghĩa là chờ nửa giây rồi chạy 2 giây. Nếu đảo hai số, chuyển động thành chạy nửa giây sau khi chờ 2 giây, và lỗi này rất khó phát hiện khi đọc lại mã.
Chạy xong hiệu ứng hiện dần thì phần tử lại biến mất, vì sao?
Vì chế độ giữ trạng thái đang để none, nên khi chuyển động kết thúc, phần tử quay về đúng kiểu dáng khai báo trong CSS thường. Nếu CSS thường không đặt opacity, phần tử trở lại trạng thái mặc định. Hãy đặt fill mode là forwards để giữ giá trị của mốc cuối, hoặc khai báo sẵn trạng thái cuối trong CSS thường.
Chế độ backwards khác forwards ở chỗ nào?
Forwards giữ giá trị của mốc cuối sau khi chạy xong. Backwards áp giá trị của mốc đầu ngay trong khoảng chờ trước khi chạy, tránh việc phần tử hiện ra ở trạng thái gốc rồi mới nhảy về trạng thái đầu. Both gộp cả hai, và đây thường là lựa chọn an toàn khi bạn có độ trễ khác không.
Vì sao lặp 2 lần và 3 lần với chiều alternate cho kết quả cuối khác nhau?
Vì alternate chạy xuôi ở các vòng lẻ và chạy ngược ở các vòng chẵn. Số vòng chẵn kết thúc bằng một lượt chạy ngược nên phần tử dừng ở trạng thái ban đầu, còn số vòng lẻ kết thúc bằng lượt chạy xuôi nên dừng ở trạng thái cuối. Hãy tính điều này khi kết hợp với chế độ giữ trạng thái forwards.
Chuyển động và transition khác nhau thế nào?
Transition chỉ nội suy giữa hai trạng thái và cần một sự kiện kích hoạt như rê chuột hay đổi lớp. Chuyển động bằng keyframes định nghĩa được nhiều mốc trung gian, tự chạy khi phần tử xuất hiện, lặp được nhiều vòng và đảo chiều được. Với hiệu ứng đơn giản hai trạng thái, transition gọn hơn và nên dùng trước.
Làm sao dừng chuyển động khi người dùng rê chuột lên?
Dùng thuộc tính animation-play-state với giá trị paused trong trạng thái hover, ví dụ đặt animation-play-state: paused cho phần tử khi rê chuột. Thuộc tính này không có trong bảng điều khiển của công cụ nên bạn thêm tay vào CSS. Khi thôi rê chuột, chuyển động chạy tiếp từ đúng chỗ đã dừng chứ không bắt đầu lại.
Làm sao cho chuyển động chạy lại từ đầu bằng JavaScript?
Gỡ lớp chứa chuyển động khỏi phần tử, buộc trình duyệt tính lại bố cục bằng cách đọc một thuộc tính như offsetWidth, rồi gắn lớp trở lại. Nếu chỉ gỡ rồi gắn ngay trong cùng một lượt xử lý, trình duyệt gộp hai thay đổi lại và chuyển động không khởi động lại.
Vì sao chuyển động bị giật trên điện thoại?
Thường vì bạn đang chạy chuyển động trên các thuộc tính buộc trình duyệt tính lại bố cục như width, height, top hay left. Hãy quy về transform và opacity, đây là hai nhóm có thể xử lý ở bước ghép lớp. Ngoài ra hãy giảm số phần tử chạy cùng lúc, vì hàng chục chuyển động song song vẫn nặng dù dùng đúng thuộc tính.
Tên keyframes có bị trùng giữa các tệp CSS không?
Có, tên keyframes có phạm vi toàn cục trong tài liệu chứ không giới hạn trong tệp hay trong lớp. Hai khối cùng tên thì khối khai báo sau ghi đè khối trước. Hãy đặt tên mô tả rõ và thêm tiền tố theo thành phần, ví dụ card-fade-in thay vì fadeIn, nhất là khi dự án có nhiều thư viện giao diện.
Thời lượng bao nhiêu là hợp lý?
Chuyển động phản hồi thao tác nên nằm trong khoảng 150 tới 300 mili giây; chuyển cảnh lớn hơn như hộp thoại trượt vào có thể 300 tới 500 mili giây; hiệu ứng chờ như vòng xoay tải thường một tới hai giây mỗi vòng và chạy vô hạn. Trên 500 mili giây cho thao tác thường xuyên sẽ tạo cảm giác giao diện chậm chạp.
Cần làm gì với người dùng bật chế độ giảm chuyển động?
Dùng truy vấn phương tiện prefers-reduced-motion để rút thời lượng xuống mức không đáng kể hoặc tắt hẳn các chuyển động lớn. Đây không phải chuyện làm cho đẹp: với người dễ chóng mặt hoặc nhạy cảm với chuyển động, hiệu ứng trượt và phóng to toàn màn hình có thể gây khó chịu thực sự khi dùng trang.
Công cụ có sửa được keyframes hoặc dùng cubic-bezier không?
Không. Tám khối keyframes ở đây là cố định và danh sách đường cong tốc độ chỉ có năm giá trị từ khóa. Muốn thêm mốc, đổi giá trị hay dùng đường cong tùy chỉnh với cubic-bezier hoặc hàm bậc thang steps cho hoạt ảnh khung tranh, bạn hãy chép mã ra rồi sửa trực tiếp trong tệp CSS của dự án.
Từ khóa liên quan
- css animation generator
- tạo css animation online
- css keyframes là gì
- cách viết @keyframes css
- animation shorthand css
- animation fill mode forwards
- animation direction alternate
- animation timing function
- css animation vs transition
- hiệu ứng fade in css
- hiệu ứng loading xoay css
- animation play state paused
- prefers-reduced-motion
- tối ưu hiệu năng animation css
- transform và opacity
- thời lượng animation bao nhiêu là hợp lý
- restart css animation javascript
- hiệu ứng bounce css
- css animation miễn phí
- công cụ tạo hiệu ứng css
