Cách tạo ảnh động CSS hiệu suất cao

Hướng dẫn này hướng dẫn bạn cách tạo ảnh động CSS hiệu suất cao.

Hãy xem bài viết Tại sao một số ảnh động bị chậm? để tìm hiểu lý thuyết đằng sau các đề xuất này.

Khả năng tương thích với trình duyệt

Tất cả các thuộc tính CSS mà hướng dẫn này đề xuất đều có khả năng hỗ trợ tốt trên nhiều trình duyệt.

transform

Hỗ trợ trình duyệt

  • Chrome: 36.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Nguồn

opacity

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 2.

Nguồn

will-change

Hỗ trợ trình duyệt

  • Chrome: 36.
  • Edge: 79.
  • Firefox: 36.
  • Safari: 9.1.

Nguồn

Di chuyển một phần tử

Để di chuyển một phần tử, hãy sử dụng giá trị từ khoá translate hoặc rotation của thuộc tính transform.

Ví dụ: để trượt một mục vào khung hiển thị, hãy sử dụng translate.

.animate {
  animation: slide-in 0.7s both;
}

@keyframes slide-in {
  0% {
    transform: translateY(-1000px);
  }
  100% {
    transform: translateY(0);
  }
}

Sử dụng rotate để xoay các phần tử. Ví dụ sau đây xoay một phần tử 360 độ.

.animate {
  animation: rotate 0.7s ease-in-out both;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

Đổi kích thước phần tử

Để đổi kích thước một phần tử, hãy sử dụng giá trị từ khoá scale của thuộc tính transform.

.animate {
  animation: scale 1.5s both;
}

@keyframes scale {
  50% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

Thay đổi chế độ hiển thị của một phần tử

Để hiển thị hoặc ẩn một phần tử, hãy sử dụng opacity.

.animate {
  animation: opacity 2.5s both;
}

@keyframes opacity {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

Tránh các thuộc tính kích hoạt bố cục hoặc tô màu

Trước khi sử dụng bất kỳ thuộc tính CSS nào cho ảnh động (ngoài transformopacity), hãy xác định tác động của thuộc tính này đối với quy trình hiển thị. Tránh mọi thuộc tính kích hoạt bố cục hoặc tô màu trừ phi việc đó thực sự cần thiết.

Buộc tạo lớp

Như đã giải thích trong phần Tại sao một số ảnh động bị chậm?, việc đặt các phần tử trên một lớp mới cho phép trình duyệt vẽ lại các phần tử đó mà không cần vẽ lại phần bố cục còn lại.

Trình duyệt thường có thể đưa ra quyết định chính xác về những mục cần đặt trên lớp mới, nhưng bạn có thể buộc tạo lớp theo cách thủ công bằng thuộc tính will-change. Như tên gọi, thuộc tính này cho trình duyệt biết rằng phần tử này sẽ được thay đổi theo một cách nào đó.

Trong CSS, bạn có thể áp dụng will-change cho bất kỳ bộ chọn nào:

body > .sidebar {
  will-change: transform;
}

Tuy nhiên, quy cách đề xuất rằng bạn chỉ nên làm việc này cho các phần tử luôn sắp thay đổi. Ví dụ: điều này có thể đúng đối với thanh bên mà người dùng có thể trượt vào và ra. Đối với các phần tử không thường xuyên thay đổi, bạn nên áp dụng will-change bằng JavaScript khi có nhiều khả năng thay đổi. Hãy nhớ cho trình duyệt đủ thời gian để thực hiện các biện pháp tối ưu hoá cần thiết và xoá thuộc tính này khi thay đổi đã dừng.

Nếu muốn buộc tạo lớp trong một trình duyệt không hỗ trợ will-change (rất có thể là Internet Explorer), bạn có thể đặt transform: translateZ(0).

Gỡ lỗi ảnh động bị giật hoặc chậm

Công cụ của Chrome cho nhà phát triển và Công cụ của Firefox cho nhà phát triển có nhiều công cụ giúp bạn tìm hiểu lý do ảnh động bị chậm hoặc bị lỗi.

Kiểm tra xem ảnh động có kích hoạt bố cục hay không

Ảnh động di chuyển một phần tử bằng cách sử dụng một thành phần khác ngoài transform có thể sẽ bị chậm. Ví dụ sau đây so sánh ảnh động sử dụng transform với ảnh động sử dụng topleft.

Không nên
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
Nên
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

Bạn có thể kiểm thử điều này trong hai ví dụ sau về Glitch và khám phá hiệu suất bằng DevTools.

Công cụ của Chrome cho nhà phát triển

  1. Mở bảng điều khiển Hiệu suất.
  2. Ghi lại hiệu suất trong thời gian chạy trong khi ảnh động đang diễn ra.
  3. Kiểm tra thẻ Tóm tắt.

Nếu bạn thấy giá trị khác 0 cho Rendering (Hiển thị) trong thẻ Summary (Tóm tắt), thì điều này có thể có nghĩa là ảnh động của bạn đang khiến trình duyệt thực hiện công việc bố cục.

Bảng Tóm tắt cho thấy 37 mili giây để kết xuất và 79 mili giây để vẽ.
Ví dụ về animation-with-top-left dẫn đến hoạt động kết xuất hình ảnh.
Bảng Tóm tắt hiển thị giá trị bằng 0 cho hoạt động kết xuất và vẽ.
Ví dụ về animation-with-transform không gây ra công việc kết xuất.

Công cụ của Firefox

Trong Công cụ của Firefox, Thác nước có thể giúp bạn biết được trình duyệt đang dành thời gian vào đâu.

  1. Mở bảng điều khiển Hiệu suất.
  2. Bắt đầu ghi lại hiệu suất trong khi ảnh động đang diễn ra.
  3. Dừng ghi và kiểm tra thẻ Waterfall (Dòng thác).

Nếu bạn thấy các mục nhập cho Recalculate Style (Tính toán lại kiểu), thì có nghĩa là trình duyệt phải quay lại đầu quy trình kết xuất dạng thác nước để kết xuất ảnh động.

Kiểm tra số khung hình bị bỏ qua

  1. Mở thẻ Rendering (Hiển thị) trong Công cụ của Chrome cho nhà phát triển.
  2. Đánh dấu vào hộp đánh dấu FPS meter (Bộ đếm FPS).
  3. Xem các giá trị trong khi ảnh động chạy.

Chú ý đến nhãn Khung ở đầu giao diện người dùng máy đo FPS. Thao tác này sẽ hiển thị các giá trị như 50% 1 (938 m) dropped of 1878. Ảnh động có hiệu suất cao có tỷ lệ phần trăm cao, chẳng hạn như 99%, nghĩa là có ít khung hình bị bỏ qua và ảnh động trông mượt mà.

Đồng hồ fps cho thấy 50% số khung hình đã bị bỏ qua
animation-with-top-left
Đồng hồ fps cho thấy chỉ có 1% số khung hình bị bỏ qua

Kiểm tra xem ảnh động có kích hoạt quá trình vẽ hay không

Một số thuộc tính tốn nhiều chi phí hơn để trình duyệt vẽ so với các thuộc tính khác. Ví dụ: mọi thứ liên quan đến hiệu ứng làm mờ (chẳng hạn như bóng) sẽ mất nhiều thời gian hơn để vẽ so với việc vẽ một hộp màu đỏ. Những khác biệt này không phải lúc nào cũng rõ ràng trong CSS, nhưng DevTools của trình duyệt có thể giúp bạn xác định những khu vực cần vẽ lại, cũng như các vấn đề hiệu suất khác liên quan đến việc vẽ.

Công cụ của Chrome cho nhà phát triển

  1. Mở thẻ Rendering (Hiển thị) trong Công cụ của Chrome cho nhà phát triển.
  2. Chọn Paint Flashing (Bắn sơn).
  3. Di chuyển con trỏ xung quanh màn hình.
Một thành phần trên giao diện người dùng được làm nổi bật bằng màu xanh lục để minh hoạ thành phần này sẽ được vẽ lại
Trong ví dụ này từ Google Maps, bạn có thể thấy các phần tử đang được vẽ lại.

Nếu bạn thấy toàn bộ màn hình nhấp nháy hoặc các khu vực được làm nổi bật mà bạn cho rằng không nên thay đổi, hãy điều tra thêm.

Nếu bạn cần xác định xem một thuộc tính cụ thể có gây ra vấn đề về hiệu suất liên quan đến hoạt động vẽ hay không, thì trình phân tích tài nguyên vẽ trong Công cụ của Chrome cho nhà phát triển có thể giúp bạn.

Công cụ cho nhà phát triển Firefox

  1. Mở phần Settings (Cài đặt) rồi thêm nút Toolbox (Hộp công cụ) để Bật/tắt tuỳ chọn vẽ nhấp nháy.
  2. Trên trang bạn muốn kiểm tra, hãy bật nút này rồi di chuyển chuột hoặc di chuyển để xem các khu vực được đánh dấu.

Kết luận

Nếu có thể, hãy hạn chế ảnh động ở opacitytransform để giữ ảnh động ở giai đoạn kết hợp của đường dẫn kết xuất. Sử dụng Công cụ cho nhà phát triển để kiểm tra xem ảnh động của bạn đang ảnh hưởng đến giai đoạn nào của đường dẫn.

Sử dụng trình phân tích sơn để xem có hoạt động sơn nào đặc biệt tốn kém hay không. Nếu bạn tìm thấy bất kỳ vấn đề nào, hãy kiểm tra xem một thuộc tính CSS khác có mang lại giao diện tương tự với hiệu suất tốt hơn hay không.

Hãy sử dụng thuộc tính will-change một cách tiết kiệm và chỉ khi bạn gặp vấn đề về hiệu suất.