Thuộc tính tỷ lệ khung hình CSS

Thuộc tính CSS giúp duy trì khoảng cách trong bố cục thích ứng.

Tỷ lệ khung hình

Browser Support

  • Chrome: 88.
  • Edge: 88.
  • Firefox: 89.
  • Safari: 15.

Source

Tỷ lệ khung hình thường được biểu thị dưới dạng hai số nguyên và dấu hai chấm trong kích thước của: chiều rộng:chiều cao hoặc x:y. Tỷ lệ khung hình phổ biến nhất cho ảnh là 4:3 và 3:2, trong khi video và các máy ảnh tiêu dùng gần đây có xu hướng có tỷ lệ khung hình 16:9.

Hai hình ảnh có cùng tỷ lệ khung hình. Một có kích thước 634 x 951 pixel, còn một có kích thước 200 x 300 pixel. Cả hai đều có tỷ lệ khung hình 2:3.
Hai hình ảnh có cùng tỷ lệ khung hình. Một có kích thước 634 x 951 pixel, còn một có kích thước 200 x 300 pixel. Cả hai đều có tỷ lệ khung hình 2:3.

Với sự ra đời của thiết kế thích ứng, việc duy trì tỷ lệ khung hình ngày càng trở nên quan trọng đối với các nhà phát triển web, đặc biệt là khi kích thước hình ảnh khác nhau và kích thước phần tử thay đổi dựa trên không gian có sẵn.

Sau đây là một số ví dụ về trường hợp cần duy trì tỷ lệ khung hình:

  • Tạo iframe thích ứng, trong đó iframe chiếm 100% chiều rộng của phần tử mẹ và chiều cao phải giữ nguyên một tỷ lệ khung hiển thị cụ thể
  • Tạo các vùng chứa giữ chỗ nội tại cho hình ảnh, video và nội dung nhúng để ngăn bố cục lại khi các mục tải và chiếm dung lượng
  • Tạo không gian đồng nhất, thích ứng cho ảnh động SVG hoặc bản trình bày dữ liệu trực quan mang tính tương tác
  • Tạo khoảng trống đồng nhất, thích ứng cho các thành phần có nhiều phần tử, chẳng hạn như thẻ hoặc ngày trên lịch
  • Tạo không gian đồng nhất, thích ứng cho nhiều hình ảnh có kích thước khác nhau (có thể dùng cùng với object-fit)

Object-fit

Việc xác định tỷ lệ khung hình giúp chúng ta điều chỉnh kích thước nội dung nghe nhìn trong một bối cảnh thích ứng. Một công cụ khác trong nhóm này là thuộc tính object-fit. Thuộc tính này cho phép người dùng mô tả cách một đối tượng (chẳng hạn như hình ảnh) trong một khối sẽ lấp đầy khối đó:

Hình ảnh minh hoạ về thuộc tính object-fit
Thể hiện nhiều giá trị object-fit. Xem bản minh hoạ trên Codepen.

Các giá trị initialfill sẽ điều chỉnh lại hình ảnh để lấp đầy không gian. Trong ví dụ này, điều này khiến hình ảnh bị bóp méo và mờ do điều chỉnh lại các pixel. Không lý tưởng. object-fit: cover sử dụng kích thước nhỏ nhất của hình ảnh để lấp đầy không gian và cắt hình ảnh cho vừa với không gian dựa trên kích thước này. Nó "phóng to" ở ranh giới thấp nhất. object-fit: contain đảm bảo rằng toàn bộ hình ảnh luôn hiển thị, và do đó, ngược lại với cover, trong đó object-fit: contain lấy kích thước của ranh giới lớn nhất (trong ví dụ trên, đây là chiều rộng) và đổi kích thước hình ảnh để duy trì tỷ lệ khung hình vốn có trong khi vừa với không gian. Trường hợp object-fit: none cho thấy hình ảnh được cắt ở giữa (vị trí đối tượng mặc định) theo kích thước tự nhiên.

object-fit: cover thường hoạt động trong hầu hết các trường hợp để đảm bảo giao diện đồng nhất khi xử lý hình ảnh có kích thước khác nhau. Tuy nhiên, bạn sẽ mất thông tin theo cách này (hình ảnh bị cắt ở các cạnh dài nhất).

Nếu những chi tiết này quan trọng (ví dụ: khi bạn chụp ảnh sản phẩm làm đẹp trên nền phẳng), thì việc cắt nội dung quan trọng là không được phép. Vì vậy, trường hợp lý tưởng sẽ là hình ảnh thích ứng có nhiều kích thước phù hợp với không gian giao diện người dùng mà không bị cắt.

Cách cũ: duy trì tỷ lệ khung hình bằng padding-top

Sử dụng phần trên cùng của khoảng đệm để đặt tỷ lệ khung hình 1:1 cho hình ảnh xem trước bài đăng trong băng chuyền.
Sử dụng padding-top để đặt tỷ lệ khung hình 1:1 cho hình ảnh xem trước bài đăng trong băng chuyền.

Để các thành phần này phản hồi nhanh hơn, chúng ta có thể sử dụng tỷ lệ khung hình. Điều này cho phép chúng tôi đặt một kích thước tỷ lệ cụ thể và dựa vào phần còn lại của nội dung nghe nhìn trên một trục riêng lẻ (chiều cao hoặc chiều rộng).

Một giải pháp hiện được chấp nhận trên nhiều trình duyệt để duy trì tỷ lệ khung hình dựa trên chiều rộng của hình ảnh được gọi là "Padding-Top Hack". Giải pháp này yêu cầu một vùng chứa mẹ và một vùng chứa con được đặt tuyệt đối. Sau đó, người dùng sẽ tính tỷ lệ khung hình dưới dạng tỷ lệ phần trăm để đặt làm padding-top. Ví dụ:

  • Tỷ lệ khung hình 1:1 = 1 / 1 = 1 = padding-top: 100%
  • Tỷ lệ khung hình 4:3 = 3 / 4 = 0,75 = padding-top: 75%
  • Tỷ lệ khung hình 3:2 = 2 / 3 = 0,66666 = padding-top: 66.67%
  • Tỷ lệ khung hình 16:9 = 9 / 16 = 0,5625 = padding-top: 56.25%

Giờ đây, khi đã xác định được giá trị tỷ lệ khung hình, chúng ta có thể áp dụng giá trị đó cho vùng chứa mẹ. Hãy xem ví dụ sau đây:

<div class="container">
  <img class="media" src="..." alt="...">
</div>

Sau đó, chúng ta có thể viết CSS sau:

.container {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 Aspect Ratio */
}

.media {
  position: absolute;
  top: 0;
}

Duy trì tỷ lệ khung hình bằng aspect-ratio

Sử dụng tỷ lệ khung hình để đặt tỷ lệ khung hình 1:1 cho hình ảnh xem trước của bài đăng trong băng chuyền.
Sử dụng aspect-ratio để đặt tỷ lệ khung hình 1:1 cho hình ảnh xem trước bài đăng trong băng chuyền.

Rất tiếc, việc tính toán các giá trị padding-top này không mấy trực quan và đòi hỏi một số chi phí bổ sung cũng như việc định vị. Với thuộc tính CSS aspect-ratiomới, ngôn ngữ để duy trì tỷ lệ khung hình rõ ràng hơn nhiều.

Với cùng một mã đánh dấu, chúng ta có thể thay thế padding-top: 56.25% bằng aspect-ratio: 16 / 9, đặt aspect-ratio thành một tỷ lệ cụ thể của width / height.

Sử dụng phần trên cùng của khoảng đệm
.container {
  width: 100%;
  padding-top: 56.25%;
}
Sử dụng tỷ lệ khung hình
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

Việc sử dụng aspect-ratio thay vì padding-top sẽ rõ ràng hơn nhiều và không cần phải đại tu thuộc tính khoảng đệm để thực hiện việc gì đó bên ngoài phạm vi thông thường của thuộc tính này.

Thuộc tính mới này cũng bổ sung khả năng đặt tỷ lệ khung hình thành auto, trong đó "các phần tử được thay thế bằng tỷ lệ khung hình nội tại sẽ sử dụng tỷ lệ khung hình đó; nếu không, hộp sẽ không có tỷ lệ khung hình ưu tiên." Nếu bạn chỉ định cả auto<ratio> cùng nhau, thì tỷ lệ khung hình ưu tiên là tỷ lệ được chỉ định của width chia cho height, trừ phi đó là một phần tử được thay thế có tỷ lệ khung hình tự nhiên. Trong trường hợp đó, tỷ lệ khung hình đó sẽ được sử dụng.

Ví dụ: tính nhất quán trong một lưới

Điều này cũng hoạt động rất hiệu quả với các cơ chế bố cục CSS như CSS Grid và Flexbox. Hãy xem xét một danh sách có các phần tử con mà bạn muốn duy trì tỷ lệ khung hình 1:1, chẳng hạn như một lưới biểu tượng nhà tài trợ:

<ul class="sponsor-grid">
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
</ul>
.sponsor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}

.sponsor img {
  aspect-ratio: 1 / 1;
  width: 100%;
  object-fit: contain;
}
Hình ảnh trong một lưới có phần tử mẹ ở nhiều kích thước tỷ lệ khung hình. Xem bản minh hoạ trên Codepen.

Ví dụ: ngăn chặn bố cục thay đổi

Một tính năng tuyệt vời khác của aspect-ratio là tính năng này có thể tạo khoảng trống của phần giữ chỗ để ngăn chặn Sự thay đổi bố cục tích luỹ và mang lại Web Vitals tốt hơn. Trong ví dụ đầu tiên này, việc tải một thành phần từ một API như Unsplash sẽ tạo ra một sự thay đổi bố cục khi nội dung nghe nhìn tải xong.

Video về độ biến động bố cục tích luỹ xảy ra khi không có tỷ lệ khung hình nào được đặt trên một thành phần đã tải. Video này được ghi lại bằng mạng 3G mô phỏng.

Mặt khác, việc sử dụng aspect-ratio sẽ tạo một phần giữ chỗ để ngăn hiện tượng bố cục thay đổi này:

img {
  width: 100%;
  aspect-ratio: 8 / 6;
}
Video có tỷ lệ khung hình cố định được đặt trên một tài sản đã tải. Video này được ghi lại bằng mạng 3G mô phỏng. Xem bản minh hoạ trên Codepen.

Mẹo bổ sung: thuộc tính hình ảnh cho tỷ lệ khung hình

Một cách khác để đặt tỷ lệ khung hình của hình ảnh là thông qua thuộc tính hình ảnh. Nếu biết trước kích thước của hình ảnh, thì phương pháp hay nhất là đặt các kích thước này làm widthheight.

Đối với ví dụ trên, khi biết kích thước là 800 x 600 pixel, mã đánh dấu hình ảnh sẽ có dạng như sau: <img src="image.jpg" alt="..." width="800" height="600">. Nếu hình ảnh được gửi có cùng tỷ lệ khung hình, nhưng không nhất thiết phải có các giá trị pixel chính xác đó, thì chúng ta vẫn có thể sử dụng các giá trị thuộc tính hình ảnh để đặt tỷ lệ, kết hợp với một kiểu width: 100% để hình ảnh chiếm không gian phù hợp. Tất cả những điều đó sẽ có dạng như sau:

<!-- Markup -->
<img src="image.jpg" alt="..." width="8" height="6">
/* CSS */
img {
  width: 100%;
  height: auto;
}

Cuối cùng, hiệu ứng này cũng giống như việc đặt aspect-ratio trên hình ảnh thông qua CSS và tránh được hiện tượng thay đổi bố cục tích luỹ (xem bản minh hoạ trên Codepen).

Kết luận

Với thuộc tính CSS aspect-ratio mới, được ra mắt trên nhiều trình duyệt hiện đại, việc duy trì tỷ lệ khung hình phù hợp trong các vùng chứa bố cục và nội dung nghe nhìn sẽ trở nên đơn giản hơn một chút.

Ảnh của Amy ShamblenLionel Gustave qua Unsplash.