Kiểm soát chặt chẽ các phép biến đổi CSS bằng các thuộc tính biến đổi riêng lẻ

Biến đổi các phần tử bằng thuộc tính translate, rotatescale

Thuộc tính transform của CSS

Để áp dụng phép biến đổi cho một phần tử, hãy sử dụng Thuộc tính transform CSS. Thuộc tính này chấp nhận một hoặc nhiều <transform-function> được áp dụng lần lượt.

.target {
  transform: translateX(50%) rotate(30deg) scale(1.2);
}

Phần tử được nhắm mục tiêu được dịch 50% trên trục X, xoay 30 độ và cuối cùng được điều chỉnh theo tỷ lệ lên 120%.

Mặc dù thuộc tính transform hoạt động tốt, nhưng sẽ hơi phiền phức khi bạn muốn thay đổi từng giá trị trong số đó.

Để thay đổi tỷ lệ khi di chuột, bạn phải sao chép tất cả các hàm trong thuộc tính biến đổi, mặc dù giá trị của các hàm này không thay đổi.

.target:hover {
  transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}

Các thuộc tính biến đổi riêng lẻ

Phiên bản Chrome 104 sẽ cung cấp các thuộc tính riêng lẻ cho các phép biến đổi CSS. Các thuộc tính này là scale, rotatetranslate. Bạn có thể sử dụng các thuộc tính này để xác định riêng từng phần của phép biến đổi.

Bằng cách đó, Chrome sẽ gia nhập Firefox và Safari vốn đã hỗ trợ các thuộc tính này.

Hỗ trợ trình duyệt

  • Chrome: 104.
  • Edge: 104.
  • Firefox: 72.
  • Safari: 14.1.

Nguồn

Viết lại ví dụ transform trước đó bằng các thuộc tính riêng lẻ, đoạn mã của bạn sẽ trở thành:

.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

Thứ tự rất quan trọng

Một điểm khác biệt chính giữa thuộc tính transform CSS ban đầu và các thuộc tính mới là thứ tự áp dụng các phép biến đổi đã khai báo.

Với transform, các hàm biến đổi được áp dụng theo thứ tự viết – từ trái (bên ngoài) sang phải (bên trong).

Với các thuộc tính biến đổi riêng lẻ, thứ tự không phải là thứ tự khai báo các thuộc tính đó. Thứ tự luôn giống nhau: trước tiên là translate (bên ngoài), sau đó là rotate, rồi đến scale (bên trong).

Điều đó có nghĩa là cả hai đoạn mã sau đây đều cho ra kết quả giống nhau:

.transform--individual {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

.transform--individual-alt {
  rotate: 30deg;
  translate: 50% 0;
  scale: 1.2;
}

Trong cả hai trường hợp, trước tiên, các phần tử được nhắm mục tiêu sẽ được dịch bởi 50% trên trục X, sau đó xoay theo 30deg và cuối cùng được điều chỉnh theo tỷ lệ bằng 1.2.

Nếu một trong các thuộc tính biến đổi riêng lẻ được khai báo cùng với thuộc tính transform, thì các phép biến đổi riêng lẻ sẽ được áp dụng trước (translate, rotate, sau đó là scale) với transform ở cuối cùng (bên trong). Bạn có thể xem thêm thông tin chi tiết trong thông số kỹ thuật xác định cách tính toán ma trận biến đổi.

Ảnh động

Lý do chính khiến chúng tôi thêm các thuộc tính này là để tạo ảnh động dễ dàng hơn. Giả sử bạn muốn tạo ảnh động cho một phần tử như sau:

Biểu đồ khung hình chính.

Sử dụng transform

Để triển khai ảnh động này bằng transform, bạn phải tính toán tất cả các giá trị trung gian cho tất cả các phép biến đổi đã xác định và đưa các giá trị đó vào mỗi khung hình chính. Ví dụ: để xoay ở mốc 10%, bạn cũng phải tính toán các giá trị cho các phép biến đổi khác vì thuộc tính transform cần tất cả các giá trị đó.

Biểu đồ khung hình chính với các giá trị trung gian được tính toán.

Mã CSS thu được sẽ có dạng như sau:

@keyframes anim {
  0% { transform: translateX(0%); }
  5% { transform: translateX(5%) rotate(90deg) scale(1.2); }
  10% { transform: translateX(10%) rotate(180deg) scale(1.2); }
  90% { transform: translateX(90%) rotate(180deg) scale(1.2); }
  95% { transform: translateX(95%) rotate(270deg) scale(1.2); }
  100% { transform: translateX(100%) rotate(360deg); }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

Sử dụng từng thuộc tính biến đổi

Với các thuộc tính biến đổi riêng lẻ, việc này trở nên dễ dàng hơn nhiều. Thay vì kéo tất cả các phép biến đổi từ khung hình chính này sang khung hình chính khác, bạn có thể nhắm đến từng phép biến đổi riêng lẻ. Bạn cũng không cần tính toán tất cả các giá trị trung gian đó nữa.

@keyframes anim {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }

  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }

  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

Sử dụng các thuộc tính biến đổi riêng lẻ và một số khung hình chính

Để tạo mã mô-đun, bạn có thể chia mỗi ảnh động phụ thành một nhóm khung hình chính riêng.

@keyframes move {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }
}

@keyframes scale {
  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }
}

@keyframes rotate {
  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: move 2s, scale 2s, rotate 2s;
  animation-fill-mode: forwards;
}

Nhờ việc phân tách này, bạn có thể áp dụng từng nhóm khung hình chính riêng biệt theo ý muốn vì các thuộc tính transform – hiện đã trở thành các thuộc tính riêng lẻ – không còn ghi đè lẫn nhau nữa. Ngoài ra, bạn có thể đặt thời gian khác nhau cho từng phép biến đổi mà không cần phải viết lại toàn bộ.

Hiệu suất

Ảnh động sử dụng các thuộc tính mới này cũng hiệu quả như ảnh động của thuộc tính transform hiện có.

Ảnh động của translate, rotatescale chạy trên trình kết hợp giống như ảnh động của transform, vì vậy, chúng rất tốt cho hiệu suất ảnh động giống như transform.

Các thuộc tính mới này cũng hoạt động với thuộc tính will-change. Nhìn chung, tốt nhất bạn nên tránh sử dụng quá nhiều will-change bằng cách sử dụng nó trên số lượng phần tử tối thiểu cần thiết và trong thời gian ngắn nhất có thể. Tuy nhiên, bạn cũng nên nêu càng cụ thể càng tốt. Ví dụ: nếu đang sử dụng will-change để tối ưu hoá ảnh động bằng các thuộc tính rotatefilter, bạn nên khai báo thông tin này bằng will-change: rotate, filter. Cách này tốt hơn một chút so với việc sử dụng will-change: transform, filter trong trường hợp bạn tạo ảnh động rotatefilter, vì một số cấu trúc dữ liệu mà Chrome tạo trước khi bạn sử dụng will-change sẽ khác với transform so với rotate.

Một phần của Loạt bài viết về các công cụ mới có khả năng tương tác