Share vì hữu ích

4 phút đọc

Bạn có biết Responsive Images trong CSS là gì và tại sao cần sử dụng nó trên website không? Hãy cùng Code Tốt khám phá cách thức làm chủ công nghệ này nhé.

Responsive Images là gì?

Khái niệm “Responsive images” chứa từ “responsive” tương tự như “responsive website” mà chúng ta hay thấy. Ta có thể tạm dịch là công nghệ “ảnh tương thích nhiều màn hình”.

Responsive Images trong code CSS

Responsive Images trong code CSS

Responsive images được biết đến từ năm 2014 với các thuộc tính “srcset” và “sizes” trong markup HTML của thẻ <img> và <picture>. Tuy nhiên, bài viết này sẽ tìm hiểu cách thức responsive images có thể hoạt động tương đồng trong file style giao diện CSS như thế nào.

srcset trong CSS

Trong HTML, srcset thường trông như thế này:

<img srcset="
 images/[email protected] 1x, 
 images/[email protected] 2x
" alt="Intro Image">

Ảnh [email protected] là ảnh cho các màn hình bình thường, và ảnh [email protected] là ảnh cho các màn hình retina (thông thường là Macbook). Nếu ta muốn làm như vậy bằng CSS, ta sẽ viết như sau:

.img {
  background-image: url('images/[email protected]'); 
}
@media
 (-webkit-min-device-pixel-ratio: 2),
 (min-resolution: 192dpi) { 
  .img {
    background-image: url('images/[email protected]');
  }
}

Bạn thấy đấy, trông có sự khác nhau phải không? srcset dường như mang lại gợi ý cho trình duyệt, và bản thân trình duyệt quyết định sẽ chọn ảnh nào phù hợp. Cách thức CSS cũng là tương tự. Các thuộc tính trong CSS @media thì đã được các trình duyệt hỗ trợ rồi.

Ngoài ra, trong CSS ta có thể sử dụng image-set() như sau:

.img {
  background-image: url(examples/images/image-384.jpg);
  background-image: 
    image-set(
    url('images/[email protected]') 1x,
    url('images/[email protected]') 2x,
  );
}

Tất nhiên, tính đến sự hỗ trợ của trình duyệt của image-set() thì không phổ thông lắm. Mặc dù trông nó có vẻ giống srcset của HTML, nhưng nó cũng không dễ dàng gì thay thế thuộc tính này.

Thuộc tính sizes trong CSS

Bạn có biết thuộc tính sizes trong markup HTML được thể hiện như thế nào không? Dưới đây là ví dụ:

<img
 sizes="(min-width: 40em) 80vw, 100vw"
 srcset=" ... "
 alt="…">

Và trông nó sẽ có vẻ giống như thế này trong CSS:

img.image {
  width: 100%;
}
@media (min-width: 40em) {
  .parent-image-block {
    width: 80%;
  }
}

Nhưng sizes nếu không sử dụng srcset thì thực ra không làm gì cả. Chẳng hạn, để sizes làm việc, markup HTML cần viết như sau:

<img
 sizes="(min-width: 400px) 80vw, 100vw"
 srcset="images/small.jpg 375w,
 images/big.jpg 1500w"
 alt="…">

Markup ở trên cung cấp cho trình duyệt thông tin để lựa chọn file ảnh tốt nhất, chẳng hạn:

Nếu viewport trình duyệt là 320px và không phải retina, tức là ảnh sẽ hiển thị ở 100vw. Trình duyệt sẽ làm phép tính tỷ lệ để lấy ra ảnh tốt nhất:

  • Ảnh 1: 375 / 320 = 1.17
  • Ảnh 2: 1500 / 320 = 4.69

Vì 1.17 gần với 1 (do không phải màn hình retina 2x), nên ảnh nào xác định 375w trong srcset sẽ được chọn.

Giờ hãy thử lấy ví dụ với màn hình retina, trình duyệt sẽ nhẩm như sau:

  • Ảnh 1: 375 / 640 = 0.59
  • Ảnh 2: 1500 / 640 = 2.34

Như vậy ảnh 2 có tỷ lệ sát với 2 nên được chọn.

Với logic dạng này, thật khó để diễn giải và sử dụng nó tương đồng trong CSS. Ta tạm thời cắt nghĩa và dịch nôm phần logic ra như sau:

  1. Nếu trình duyệt có viewport nhỏ hơn 375px, sử dụng ảnh 375w.
  2. Nếu trình duyệt có viewport lớn hơn 375px, nhưng nhỏ hơn 400px, sử dụng ảnh 1500w.
  3. Ở khung 400px, ảnh chuyển sang kích thước 80vw, tức là vẫn có thể sử dụng ảnh 375w.
  4. Trên 468px, chỉ dùng ảnh 1500w.

Như vậy, bằng CSS, ta thể hiện như sau:

img {
  background-image: url(small.jpg);
}
@media 
 (min-width: 375px) and (max-width: 400px),
 (min-width: 468px) {
  .parent-image-block {
   background-image: url(large.jpg);
  }
}

Trong cụ thể tình huống ví dụ ở trên, ở khung hình retina, mặc dù có khung hình 300px thì vẫn cần ảnh có kích thước là 600px, nên ta thêm vào logic thành:

img.image {
  background-image: url('small.jpg');
}
@media 
 (min-width: 375px) and (max-width: 400px),
 (min-width: 468px),
 (-webkit-min-device-pixel-ratio: 2), 
 (min-resolution: 192dpi) {
   .parent-image-block {
     background-image: url('large.jpg');
   }
}

Sự thay đổi này làm tăng các điểm thay đổi hình ảnh. Dù vậy, nó không phải phương án hoàn hảo và cũng có thể ảnh hưởng tới các yếu tố tốc độ web, ví dụ như băng thông tải về trình duyệt.

Kết luận

Qua sự phân tích về cách ta sử dụng hai thuộc tính srcset và sizes trong markup HTML và chuyển đổi nó qua logic của CSS, mình hi vọng các bạn nắm được cách thức ta sử dụng trong CSS. Dẫu vậy, bạn vẫn nên cân nhắc sử dụng markup HTML thay vì trong CSS để dễ dàng thiết lập các yếu tố giúp trình duyệt lựa chọn phương án tối ưu hơn.

Bài viết lược dịch từ CSS-Trick.

 

Share vì hữu ích

Tác giả: Khôi 'Pro' Nguyễn

Technical Lead tại Solis Lab. Quản lý ngôn ngữ tại vi.wordpress.org.

Trả lời