Biến đổi các phần tử bằng thuộc tính translate
, rotate
và scale
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. Tài sản 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
thực hiện công việc của mình tốt, nhưng nó sẽ trở nên hơi tẻ nhạt khi bạn muốn thay đổi bất kỳ giá trị nào trong số đó riêng lẻ.
Để 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
, rotate
và translate
. 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.
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 (bên trong). Bạn có thể xem thêm thông tin chi tiết trong phần thông số kỹ thuật để xác định cách tính 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:
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 ở điểm đánh dấu 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ị đó.
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 riêng lẻ
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 phải 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. Ở trên, bạn có thể cho mỗi phép biến đổi một thời gian khác nhau 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
, rotate
và scale
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 rotate
và filter
, 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 rotate
và filter
, 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