Tính toán bằng kích thước nội tại

Tính năng web: calc-size() interpolate-size

calc-size() là một hàm CSS để thực hiện các phép toán trên các từ khoá định cỡ nội tại như auto, min-content và fit-content. BẮT BUỘC: Chỉ sử dụng calc-size() khi bạn cần sửa đổi kích thước nội tại bằng một phép tính hoặc quy tắc ràng buộc; đối với ảnh động đơn giản dựa trên từ khoá (ví dụ: 0 đến auto), bạn phải sử dụng interpolate-size: allow-keywords.

Các bước triển khai

  1. Xác định cơ sở nội tại: Xác định từ khoá nội tại nào (auto, min-content, v.v.) sẽ tạo thành cơ sở cho phép tính của bạn.
  2. Xác định các quy tắc ràng buộc: Sử dụng các hàm toán học CSS như clamp(), min() hoặc max() trong đối số thứ hai để thực thi các quy tắc ràng buộc về thiết kế đối với kích thước nội tại.
  3. BẮT BUỘC: Cung cấp giá trị dự phòng: Luôn khai báo từ khoá hoặc độ dài kích thước chuẩn ngay trước thuộc tính sử dụng calc-size() để đảm bảo bố cục vẫn hoạt động trong các trình duyệt không được hỗ trợ.
  4. Áp dụng thuộc tính logic: Mặc định sử dụng các thuộc tính logic như inline-size hoặc block-size để đảm bảo các phép tính tuân thủ chế độ viết của tài liệu.
  5. Không bắt buộc: Cải tiến tăng dần: Gói logic bố cục phức tạp hoặc ảnh động trong khối @supports (inline-size: calc-size(auto, size + 0px)) để chỉ cung cấp các tính năng nâng cao cho những trình duyệt có khả năng.

Cú pháp cơ bản

/* calc-size(<calc-size-basis>, <calc-sum>) — mathematical operations on intrinsic sizing keywords */
.element {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: min-content;
  
  /* DO: Use calc-size to modify an intrinsic basis with a calculation or function */
  inline-size: calc-size(min-content, size + 2rem);
}

Đối số cơ sở hợp lệ (<calc-size-basis>)

Đối số đầu tiên xác định kích thước "cơ sở" cho phép tính.

Từ khoá chuẩn:

  • auto: Kích thước mặc định cho phần tử.
  • min-content: Kích thước nhỏ nhất mà phần tử có thể nhận mà không bị tràn.
  • max-content: Kích thước mà phần tử cần có để chứa tất cả nội dung trên một dòng.
  • fit-content: Tương đương với clamp(min-content, auto, max-content).
  • content: Chỉ hợp lệ khi calc-size() được dùng trong thuộc tính flex-basis.

Đối số đặc biệt:

  • any: Cơ sở chung được sử dụng khi không xác định được loại nội tại cụ thể hoặc khi lồng các phép tính.
  • calc-size() lồng nhau: Cho phép tính toán nhiều bước hoặc có điều kiện.
  • <calc-sum>: Một độ dài, tỷ lệ phần trăm hoặc biểu thức toán học cụ thể (ví dụ: 100px hoặc 20%). Khi một giá trị cố định được dùng làm cơ sở, từ khoá size vẫn có sẵn (nhưng chỉ trong đối số thứ hai) và đại diện cho giá trị đã phân giải của cơ sở đó.

BẮT BUỘC: Từ khoá size không hợp lệ trong chính đối số đầu tiên (<calc-size-basis>). Đây là một biến cục bộ chỉ tồn tại để tham chiếu lại cơ sở từ trong đối số thứ hai (<calc-sum>).

Đối số tính toán hợp lệ (<calc-sum>)

Đối số thứ hai là biểu thức toán học.

  • Nó thường sử dụng từ khoá size để tham chiếu đến giá trị của cơ sở.
  • Mặc dù từ khoá size về mặt kỹ thuật là không bắt buộc, nhưng việc bỏ qua từ khoá này có nghĩa là phép tính sẽ phân giải thành một giá trị cố định, bỏ qua hoàn toàn cơ sở.
  • Công thức này có thể bao gồm các toán tử toán học chuẩn (+, -, *, /).
  • Giá trị này có thể bao gồm các hàm toán học CSS như clamp(), min(), max() và round().
  • BẮT BUỘC: calc-size() chỉ cho phép một giá trị kích thước nội tại (cơ sở) trong mỗi phép tính. Bạn không thể kết hợp các từ khoá định cỡ nội tại trong cùng một lệnh gọi calc-size().

Trường hợp sử dụng

Tạo ảnh động đến và từ Kích thước nội tại

Theo mặc định, trình duyệt không thể nội suy giữa chiều dài (ví dụ: 0px) và từ khoá nội tại (ví dụ: auto). Việc gói từ khoá trong calc-size() sẽ biến từ khoá đó thành một giá trị có thể nội suy.

Chọn công cụ phù hợp cho ảnh động

  • BẮT BUỘC: Sử dụng interpolate-size: allow-keywords: Đối với ảnh động đơn giản đến hoặc từ kích thước nội tại (ví dụ: height: 0 đến height: auto) mà không có bất kỳ sửa đổi toán học nào. Đây là phương pháp bắt buộc để nội suy từ khoá đơn giản và lý tưởng nhất là nên áp dụng trên toàn hệ thống thông qua :root.

    :root {
      /* Best practice: Enable keyword interpolation globally */
      interpolate-size: allow-keywords;
    }
    
    .item {
      height: 0;
      transition: height 0.3s ease;
    }
    
    .item.open {
      /* Simple interpolation from 0 to auto now works without calc-size() */
      height: auto;
    }
    
  • Sử dụng calc-size(): CHỈ khi bạn cần thực hiện các phép tính toán học trên một kích thước nội tại trong quá trình chuyển đổi (ví dụ: thêm khoảng đệm hoặc kẹp kích thước).

.accordion-content {
  display: block;
  overflow: hidden;
  /* MANDATORY: Fallback value for closed state */
  block-size: 0;
  transition: block-size 0.3s ease-out;
}

.accordion-content.open {
  /* MANDATORY: Fallback value for open state */
  block-size: auto;

  /* 
    DO: Use calc-size(auto, ...) to enable animation from 0 to the element's 
    intrinsic size while doing a calculation (in this case, adding a space of 2rem).
  */
  block-size: calc-size(auto, size + 2rem);
}

BẮT BUỘC: Không thể nội suy trực tiếp giữa hai từ khoá định cỡ nội tại. Một đầu của hiệu ứng chuyển đổi phải là độ dài hoặc tỷ lệ phần trăm.

Tôn trọng lựa chọn ưu tiên của người dùng về chuyển động

Ảnh động thay đổi kích thước của các vùng bố cục lớn có thể gây ảnh hưởng đặc biệt đến người dùng bị rối loạn tiền đình. BẮT BUỘC: Luôn tôn trọng lựa chọn ưu tiên của người dùng về chuyển động bằng cách sử dụng truy vấn nội dung nghe nhìn prefers-reduced-motion để đơn giản hoá hoặc giảm thiểu ảnh động không cần thiết. Các chiến lược phổ biến bao gồm tắt hoàn toàn chuyển động, giảm thời lượng hoặc thay thế các thay đổi về bố cục bằng hiệu ứng chuyển đổi độ mờ tinh tế.

.accordion-content {
  opacity: 0;
  transition: block-size 0.3s ease, opacity 0.3s ease;
}

.accordion-content.open {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .accordion-content {
    /* 
       EXAMPLE: Replacing disruptive layout animations with a subtle fade-in.
       Setting the block-size instantly and transitioning opacity 
       provides a clear state change without large-scale motion.
    */
    transition: opacity 1.5s ease;
  }

  .accordion-content.open {
    /* Jump the size instantly */
    block-size: auto;
  }
}

Áp dụng các quy tắc ràng buộc cho kích thước nội tại

Bạn có thể sử dụng calc-size() với bất kỳ hàm toán học CSS nào (chẳng hạn như min(), max(), clamp() hoặc round()) để đảm bảo kích thước nội tại của một phần tử nằm trong ranh giới thiết kế.

.dynamic-container {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: fit-content;

  /* 
    DO: Establish a dynamic size based on content, while:
    1. Enforcing boundaries using CSS math functions (min, clamp, etc.)
    2. Modifying the intrinsic size with fixed or relative offsets
  */
  inline-size: calc-size(fit-content, min(size + var(--extra-space), var(--max-allowed)));
}

Những điểm quan trọng cần lưu ý

  • Cạm bẫy về tỷ lệ phần trăm: Tỷ lệ phần trăm bên trong <calc-sum> được phân giải dựa trên kích thước của vùng chứa, chứ không phải từ khoá size. Ví dụ: calc-size(auto, size + 10%) thêm 10% chiều rộng của phần tử mẹ vào chiều rộng auto của phần tử, điều này có thể dẫn đến kết quả không mong muốn hoặc tràn.
  • Yêu cầu về phép tính: BẮT BUỘC: Sử dụng interpolate-size: allow-keywords thay vì calc-size() cho ảnh động đơn giản (ví dụ: 0 đến auto). Bạn chỉ nên sử dụng calc-size() khi bố cục yêu cầu điều chỉnh toán học động cho cơ sở nội tại.
  • Lưu ý về hiệu suất: Việc tạo ảnh động cho các thuộc tính mô hình hộp như inline-size hoặc block-size sẽ kích hoạt việc tính toán lại bố cục, điều này có thể tốn kém. Sử dụng ảnh động calc-size() chủ yếu cho các phần tử quan trọng về bố cục khi các lựa chọn thay thế không liên quan đến bố cục không đủ đáp ứng.

Chiến lược dự phòng

calc-size() và interpolate-size là các cải tiến tăng dần. Trong các trình duyệt không hỗ trợ, các thuộc tính sẽ bị bỏ qua và bố cục sẽ vẫn hoạt động, mặc dù ảnh động cho các từ khoá nội tại sẽ nhảy thay vì chuyển đổi. Luôn cung cấp từ khoá hoặc độ dài chuẩn làm phương án dự phòng.

.element {
  /* Fallback for browsers that don't support calc-size() */
  inline-size: fit-content; 
  /* Modern browsers will override the fallback */
  inline-size: calc-size(fit-content, size + 2rem);
}

Ảnh động và hiệu ứng chuyển đổi dự phòng

Trong các trình duyệt không hỗ trợ calc-size() hoặc interpolate-size, các hiệu ứng chuyển đổi liên quan đến từ khoá định cỡ nội tại sẽ không nội suy được.

  • Xuống cấp nhẹ: Chế độ dự phòng mặc định là "chuyển đổi tức thì" giữa các trạng thái (ví dụ: từ 0 sang auto). Điều này thường được chấp nhận vì bố cục vẫn hoạt động.
  • Trải nghiệm nâng cao: Sử dụng @supports để áp dụng logic bố cục phức tạp hoặc kiểu bổ sung chỉ có ý nghĩa khi có thể tạo ảnh động nội tại mượt mà.
  • Tránh các phép đo dựa trên JS: Mặc dù bạn có thể sử dụng JavaScript để đo lường các phần tử và tạo ảnh động cho kích thước của chúng theo cách thủ công, nhưng việc này thường không cần thiết và có thể dẫn đến tình trạng gián đoạn bố cục. Bạn nên sử dụng tính năng "chuyển ngay" gốc làm phương án dự phòng cho các ứng dụng web hiện đại.

Đối với ảnh động, trải nghiệm dự phòng sẽ là chuyển ngay sang kích thước cuối cùng. Cách phát hiện khả năng hỗ trợ trong CSS hoặc JavaScript:

/* CSS Feature Detection */
@supports (inline-size: calc-size(auto, size + 0px)) {
  .element {
    /* Apply advanced logic only when supported */
  }
}
/* JavaScript Feature Detection */
if (CSS.supports('inline-size', 'calc-size(auto, size + 0px)')) {
  // Apply advanced sizing or animations
}