Sử dụng thuộc tính interpolate-size
hoặc hàm calc-size()
để bật các hiệu ứng chuyển đổi và ảnh động mượt mà từ độ dài sang từ khoá định cỡ nội tại và ngược lại.
Ngày xuất bản: 17 tháng 9 năm 2024
Giới thiệu
Tính năng CSS thường được yêu cầu là khả năng tạo ảnh động cho height: auto
. Một biến thể nhỏ của yêu cầu đó là chuyển đổi thuộc tính width
thay vì height
hoặc chuyển đổi sang bất kỳ kích thước nội tại nào khác được biểu thị bằng các từ khoá như min-content
, max-content
và fit-content
.
Ví dụ: trong bản minh hoạ sau, sẽ rất tuyệt nếu các nhãn có thể tạo hiệu ứng ảnh động mượt mà theo chiều rộng tự nhiên khi di chuột qua các biểu tượng.
CSS được sử dụng như sau:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease; /* 👈 Transition the width */
&:hover,
&:focus-visible {
width: max-content; /* 👈 Doesn't work with transitions */
}
}
Mặc dù transition
được khai báo để chuyển đổi thuộc tính width
và width: auto
được khai báo trên :hover
, nhưng không có quá trình chuyển đổi nào diễn ra suôn sẻ. Thay vào đó, sự thay đổi diễn ra đột ngột.
Tạo ảnh động đến và từ các từ khoá định cỡ nội tại bằng interpolate-size
Thuộc tính interpolate-size
của CSS cho phép bạn kiểm soát việc có cho phép ảnh động và hiệu ứng chuyển đổi của các từ khoá định cỡ nội tại CSS hay không.
Giá trị mặc định là numeric-only
không bật tính năng nội suy. Khi đặt thuộc tính thành allow-keywords
, bạn chọn sử dụng nội suy từ độ dài đến từ khoá định cỡ nội tại CSS trong trường hợp trình duyệt có thể tạo ảnh động cho các từ khoá đó.
Theo thông số kỹ thuật:
numeric-only
: Không thể nội suy<intrinsic-size-keyword>
.allow-keywords
: Bạn có thể nội suy hai giá trị nếu một trong hai giá trị là<intrinsic-size-keyword>
và giá trị còn lại là<length-percentage>
. […]
Vì thuộc tính interpolate-size
là thuộc tính kế thừa, nên bạn có thể khai báo thuộc tính này trên :root
để bật tính năng chuyển đổi đến và từ các từ khoá định cỡ nội tại cho toàn bộ tài liệu. Đây là phương pháp đề xuất.
/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
Trong bản minh hoạ sau, quy tắc này được thêm vào mã. Do đó, ảnh động đến và đi từ width: auto
hoạt động tốt (trong các trình duyệt có hỗ trợ):
Giới hạn phạm vi áp dụng lựa chọn sử dụng bằng cách thu hẹp bộ chọn
Nếu bạn chỉ muốn giới hạn việc chọn sử dụng allow-keywords
cho một cây con của tài liệu, hãy điều chỉnh bộ chọn từ :root
thành chỉ phần tử mà bạn muốn nhắm đến. Ví dụ: trong trường hợp <header>
của trang không tương thích với các loại hiệu ứng chuyển đổi này, bạn có thể chỉ giới hạn việc chọn sử dụng cho phần tử <main>
và các phần tử con của phần tử đó như sau:
main { /* 👈 Scope the opt-in to only <main> and its descendants */
interpolate-size: allow-keywords;
}
Tại sao không cho phép ảnh động đến và đi từ từ khoá định cỡ theo mặc định?
Một ý kiến phản hồi phổ biến về cơ chế chọn sử dụng này là trình duyệt chỉ nên cho phép chuyển đổi và ảnh động từ từ khoá định cỡ nội tại sang độ dài theo mặc định.
Tuỳ chọn bật hành vi này đã được nghiên cứu trong quá trình phát triển tính năng. Nhóm làm việc phát hiện rằng việc bật tính năng này theo mặc định không tương thích ngược vì nhiều trang kiểu giả định rằng không thể tạo ảnh động cho các từ khoá định cỡ nội tại (chẳng hạn như auto
hoặc min-content
). Bạn có thể xem thông tin chi tiết trong bình luận này về vấn đề liên quan của Nhóm làm việc về CSS.
Do đó, thuộc tính này là thuộc tính tuỳ chọn. Nhờ đặc điểm kế thừa, việc chọn sử dụng toàn bộ tài liệu chỉ là một nội dung khai báo interpolate-size: allow-sizes
trên :root
như đã nêu chi tiết trước đó.
Tạo ảnh động đến và từ các từ khoá định cỡ nội tại bằng calc-size()
Một cách khác để bật tính năng nội suy đến và từ các từ khoá định cỡ nội tại là sử dụng hàm calc-size()
. Phương thức này cho phép thực hiện các phép toán trên kích thước nội tại theo cách an toàn và được xác định rõ ràng.
Hàm này chấp nhận hai đối số, theo thứ tự:
- Cơ sở kích thước tính toán, có thể là
<intrinsic-size-keyword>
nhưng cũng có thể làcalc-size()
lồng nhau. - Tính toán kích thước tính toán, cho phép bạn thực hiện các phép tính bằng cách sử dụng cơ sở kích thước tính toán. Để tham chiếu đến cơ sở kích thước tính toán, hãy sử dụng từ khoá
size
.
Dưới đây là một số ví dụ:
width: calc-size(auto, size); // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered
Thêm calc-size()
vào bản minh hoạ ban đầu, mã sẽ có dạng như sau:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: calc-size(max-content, size); /* 👈 */
}
}
Về mặt hình ảnh, kết quả hoàn toàn giống như khi sử dụng interpolate-size
. Vì vậy, trong trường hợp cụ thể này, bạn nên sử dụng interpolate-size
.
calc-size()
tỏa sáng ở khả năng tính toán, đây là điều không thể làm được với interpolate-size
:
width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5); // = Half the max-content width
Ví dụ: nếu muốn tất cả các đoạn văn trên một trang có kích thước bằng bội số gần nhất của 50px
, bạn có thể sử dụng đoạn mã sau:
p {
width: calc-size(fit-content, round(up, size, 50px));
height: calc-size(auto, round(up, size, 50px));
}
calc-size()
cũng cho phép bạn nội suy giữa hai calc-size()
khi cả hai cơ sở kích thước tính toán đều giống nhau. Đây cũng là điều không thể thực hiện được với interpolate-size
.
#element {
width: min-content; /* 👈 */
transition: width 0.35s ease;
&:hover {
width: calc-size(min-content, size + 10px); /* 👈 */
}
}
Tại sao không cho phép <intrinsic-size-keyword>
trong calc()
?
Một câu hỏi thường xuất hiện với calc-size()
là tại sao Nhóm làm việc về CSS không điều chỉnh hàm calc()
để hỗ trợ các từ khoá định cỡ nội tại.
Một trong những lý do là bạn không được phép kết hợp các từ khoá định cỡ nội tại khi thực hiện phép tính. Ví dụ: bạn có thể muốn viết calc(max-content - min-content)
trông có vẻ hợp lệ, nhưng thực tế thì không phải vậy. calc-size()
thực thi tính chính xác vì không giống như calc()
, hàm này chỉ chấp nhận một <intrinsic-size-keyword>
duy nhất làm đối số đầu tiên.
Một lý do khác là khả năng nhận biết ngữ cảnh. Một số thuật toán bố cục có hành vi đặc biệt đối với các từ khoá định cỡ nội tại cụ thể. calc-size()
được xác định rõ ràng để biểu thị kích thước nội tại, chứ không phải <length>
. Nhờ đó, các thuật toán đó có thể coi calc-size(<intrinsic-size-keyword>, …)
là <intrinsic-size-keyword>
, duy trì hành vi đặc biệt của từ khoá đó.
Phương pháp nào nên dùng?
Trong hầu hết các trường hợp, hãy khai báo interpolate-size: allow-keywords
trên :root
. Đây là cách dễ nhất để bật ảnh động đến và từ các từ khoá định cỡ nội tại vì về cơ bản, đây là một dòng.
/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
Đoạn mã này là một điểm cải tiến dần dần thú vị, vì những trình duyệt không hỗ trợ đoạn mã này sẽ quay lại sử dụng không có hiệu ứng chuyển đổi.
Khi cần kiểm soát chi tiết hơn đối với các hoạt động (chẳng hạn như tính toán) hoặc bạn muốn sử dụng một hành vi mà chỉ calc-size()
mới có thể thực hiện, bạn có thể sử dụng calc-size()
.
#specific-element {
width: 50px;
&:hover {
width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
}
}
Tuy nhiên, khi sử dụng calc-size()
trong mã, bạn cần phải thêm các phương án dự phòng cho những trình duyệt không hỗ trợ calc-size()
. Ví dụ: thêm các nội dung khai báo kích thước bổ sung hoặc quay lại phát hiện tính năng bằng @supports
.
width: fit-content;
width: calc-size(fit-content, size + 1em);
/* 👆 Browsers with no calc-size() support will ignore this second declaration,
and therefore fall back to the one on the line before it. */
Các bản minh hoạ khác
Dưới đây là một số bản minh hoạ khác sử dụng interpolate-size: allow-keywords
để phát huy lợi thế.
Thông báo
Bản minh hoạ sau đây là một nhánh của bản minh hoạ @starting-style
này. Mã đã được điều chỉnh để cho phép thêm các mục có chiều cao khác nhau.
Để đạt được điều này, toàn bộ trang sẽ chọn sử dụng tính năng nội suy từ khoá theo kích thước và height
trên mỗi phần tử .item
được đặt thành auto
. Nếu không, mã sẽ giống hệt như trước khi phân nhánh.
:root {
interpolate-size: allow-keywords; /* 👈 */
}
.item {
height: auto; /* 👈 */
@starting-style {
height: 0px;
}
}
Tạo ảnh động cho phần tử <details>
Một trường hợp sử dụng thông thường mà bạn muốn sử dụng loại nội suy này là tạo ảnh động cho tiện ích thông tin công bố hoặc bảng điều khiển độc quyền khi mở. Trong HTML, bạn sử dụng phần tử <details>
cho việc này.
Với interpolate-size: allow-keywords
, bạn có thể làm được nhiều việc:
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
details {
transition: height 0.5s ease;
height: 2.5rem;
&[open] {
height: auto;
overflow: clip; /* Clip off contents while animating */
}
}
}
Tuy nhiên, như bạn có thể thấy, ảnh động chỉ chạy khi tiện ích thông tin đang mở. Để giải quyết vấn đề này, Chrome đang phát triển ::details-content
giả lập sẽ được cung cấp trong Chrome vào cuối năm nay (và sẽ được đề cập trong một bài đăng sau này). Khi kết hợp interpolate-size: allow-keywords
và ::details-content
, bạn có thể nhận được ảnh động theo cả hai hướng: