Image Responsive - Picture Tag - Tối ưu hình ảnh trên mọi thiết bị di động

Hình ảnh nổi tiếng là một trong những khía cạnh thách thức nhất của thiết kế web đáp ứng (responsive). Hôm nay chúng ta sẽ xem xét cách làm thế nào phần tử <picture>, một giải pháp cho vấn đề của hình ảnh có tính đáp ứng, có thể được sử dụng ngay bây giờ.

Đầu tiên, vấn đề

Những ngày của những trang web có chiều rộng cố định, pexel perfect thật sự đã ở lại phía sau chúng ta. Trong thời đại của màn hình rộng, internet TV, máy tính bảng và điện thoại thông minh có kích thước khác nhau, giờ đây thiết kế của chúng ta có để phục vụ cho tất cả mọi thứ từ rộng 320px cho đến 7680px.

Với nhiều độ phân giải khác nhau này dẫn đến một nhu cầu cho các hình ảnh để giãn ra hoặc thu nhỏ để phù hợp với những yêu cầu chiều rộng khác nhau. Điều này có thể chứng tỏ nó có vấn đề, ngoài hình ảnh véc tơ ra, đại đa số các hình ảnh có điểm ảnh cụ thể không thay đổi dựa trên chiều rộng.

Vậy chúng ta làm gì?

Hiện tại, giải pháp phổ biến nhất

Thường thường, bạn sẽ thấy những điều sau đây ở trong CSS của các trang web có tính đáp ứng:

img {      
max-width: 100%;      
height: auto;  
}

Đoạn code này sử dụng thiết lập max-width: 100%; để bảo đảm hình ảnh không bao giờ lớn hơn chiều rộng của phần tử chứa nó. Nếu phần tử cha thu nhỏ hơn chiều rộng của tấm hình, thì hình ảnh cũng sẽ thay đổi kích thước theo nó. Thiết lập height: auto;, đảm bảo tỷ lệ hình ảnh được bảo toàn khi điều này xảy ra.


Một hình ảnh thay đổi kích cỡ cho mọi trường hợp.

Nó giải quyết vấn đề đối với một khía cạnh, cho phép chúng ta hiển thị cùng một hình ảnh trong nhiều hoàn cảnh khác nhau. Nhưng nó không cho phép chúng ta xác định các hình ảnh khác nhau cho những hoàn cảnh khác nhau.

Một giải pháp mới: <picture>

<picture> là một phần tử mới được thiết lập để trở thành một phần chính thức của HTML5.

Nó sẽ mang lại cho quá trình đặt các hình ảnh có tính đáp ứng tương tự như các phần tử <audio><video> đang làm. Nó sẽ cho phép bạn đặt nhiều thẻ source, mỗi cái xác định tên tập tin hình ảnh khác nhau cùng với các điều kiện theo đó chúng sẽ được nạp.

Nó sẽ cho phép bạn tải một hình ảnh hoàn toàn khác nhau tùy thuộc vào:

  • Kết quả của Media Query, ví dụ viewport height, width, orientation
  • Mật độ điểm ảnh

Điều này lần lượt có nghĩa là bạn có thể:

  • Tải các hình ảnh có kích thước tương ứng, tối ưu hoá việc sử băng thông.
  • Tải các hình ảnh với kích thước khác nhau để phù hợp với thay đổi của layout ở những độ rộng khác nhau.
  • Tải các hình ảnh có độ phân giải cao cho màn hình có mật độ điểm ảnh cao hơn.


Các hình ảnh khác nhau, tùy thuộc vào hoàn cảnh

Phần tử <picture> hoạt động thế nào?

Các bước cơ bản để làm việc với <picture> là:

  1. Tạo các thẻ đóng và mở <picture></picture>.
  2. Trong các thẻ đó, tạo ra một phần tử <source> cho mỗi truy vấn bạn muốn chạy.
  3. Thêm một thuộc tính media có chứa các truy vấn của bạn về những thứ như viewport height, width, orientation vv.
  4. Thêm một thuộc tính srcset với tên tập tin hình ảnh tương ứng để tải.
  5. Thêm các tên tập tin phụ vào thuộc tính srcset của bạn nếu bạn muốn cung cấp cho các màn hình có mật độ điểm ảnh khác nhau, ví dụ như màn hình Retina.
  6. Thêm một phần tử <img> để dự phòng.

Dưới đây là một ví dụ cơ bản trong đó kiểm tra nếu các khung nhìn nhỏ hơn 768px, thì sẽ tải một hình ảnh nhỏ hơn:

<picture>      
  <source srcset="smaller.jpg" media="(max-width: 768px)">      
  <source srcset="default.jpg">      
  <img srcset="default.jpg" alt="My default image">  
</picture>

Bạn sẽ thấy rằng cú pháp sử dụng trong thuộc tính media là giống như bạn có thể sử dụng để tạo các Media Query trong CSS. Bạn có thể sử dụng các kiểm tra tương tự, có nghĩa là bạn có thể truy vấn max-widthmin-widthmax-heightmin-heightorientation và vân vân.

Bạn có thể sử dụng các kiểm tra này để làm những việc như tải các phiên bản ngang hoặc dọc của một tấm hình tùy thuộc vào hướng xoay của thiết bị, và bạn vẫn có thể kết hợp trong các truy vấn kích thước cùng lúc. Ví dụ:

<picture>      
  <source srcset="smaller_landscape.jpg" media="(max-width: 40em) and (orientation: landscape)">      
  <source srcset="smaller_portrait.jpg" media="(max-width: 40em) and (orientation: portrait)">      
  <source srcset="default_landscape.jpg" media="(min-width: 40em) and (orientation: landscape)">      
  <source srcset="default_portrait.jpg" media="(min-width: 40em) and (orientation: portrait)">      
  <img srcset="default_landscape.jpg" alt="My default image">  
</picture>

Code ở trên tải phiên bản hình ảnh nhỏ hơn, hướng nằm ngang trên một thiết bị nhỏ hơn và xoay ngang. Nó tải một phiên bản lớn hơn của cùng một hình ảnh trên một thiết bị xoay ngang.

Nếu thiết bị là nằm thẳng đứng nó tải một bức ảnh đứng, kích thước nhỏ trên một thiết bị nhỏ hoặc kích thước lớn trên một thiết bị lớn.

Nếu bạn muốn cung cấp các phiên bản độ phân giải khác nhau của hình ảnh cho màn hình có độ phân giải cao, thì bạn làm điều đó bằng cách thêm tên tập tin phụ vào thuộc tính srcset. Ví dụ, hãy xem đoạn code đầu tiên của chúng ta ở trên với việc thêm vào cho độ phân giải 2x của màn hình Retina:

<picture>      
  <source srcset="smaller.jpg, smaller_retina.jpg 2x" media="(max-width: 768px)">      
  <source srcset="default.jpg, default_retina.jpg 2x">      
  <img srcset="default.jpg, default_retina.jpg 2x" alt="My default image">  
</picture>

Media Query vẫn được xem xét trước vì thế bạn có thể kiểm soát kích thước hình ảnh sẽ xuất hiện trên màn hình. Sau đó, độ phân giải của màn hình sẽ được kiểm tra và nếu độ phân giải cao hơn được hỗ trợ thì phiên bản độ phân giải cao hơn của hình ảnh sẽ được nạp.

Sử dụng <picture> ngay hôm nay

Hiện tại, <picture> hoạt động trong Chrome, Firefox và Opera. Trong tương lai có thể chúng ta sẽ thấy sự hỗ trợ sẽ trở nên phổ biến, rộng rãi hơn khi các trình duyệt khác cũng bắt đầu cài đặt. Nhưng hiện tại thì vẫn chưa hỗ trợ.

Tuy nhiên, bạn không cần phải chờ đợi nếu bạn muốn bắt đầu sử dụng <picture> ngay bây giờ. Bạn chỉ cần sử dụng Picturefill 2.0; một polyfill cung cấp bởi những người thông minh tại Filament Group.

<script src="picturefill.js"></script>

Cũng có một tuỳ chọn để tải các script không đồng bộ để tăng hiệu quả, bạn có thể đọc về nó trong tài liệu hướng dẫn của Picturefill.

Với script này được nạp, thì phần tử <picture> sẽ làm việc như tôi đã giải thích, chỉ với một vài hạn chế.

Hạn chế của Picturefill

IE9

Picturefill hoạt động tốt với các phiên bản IE khác, tuy nhiên IE9 không nhận ra phần tử source được gói trong thẻ picture. Để giải quyết việc này, đặt các phần tử source của bạn một cách có điều kiện trong các thẻ video sẽ làm cho chúng có thể được nhìn thấy bởi IE9, ví dụ:

<picture>      <!--[if IE 9]><video style="display: none;"><![endif]-->      
  <source srcset="smaller.jpg" media="(max-width: 768px)">      
  <source srcset="default.jpg">      <!--[if IE 9]></video><![endif]-->      
  <img srcset="default.jpg" alt="My default image">  
</picture>

Android 2.3

Giống như IE9, Android 2.3 không thể thấy các phần tử source bên trong một phần tử picture. Tuy nhiên, nó có thể hiểu thuộc tính srcset khi sử dụng trên một thẻ img thông thường. Hãy chắc chắn là luôn luôn thêm phần tử dự phòng img của bạn với tên tập tin mặc định trong các thuộc tính srcset cho Android 2.3 và bất kỳ trình duyệt nào khác gặp vấn đề tương tự như trên.

Yêu cầu JavaScript và Media Query

Là một giải pháp dựa trên JavaScript, nó đương nhiên yêu cầu JavaScript để được kích hoạt trong trình duyệt. Picturefill 2.0 không cung cấp một giải pháp "no-js" bởi vì nếu nó làm vậy, nhiều hình ảnh sẽ xuất hiện khi trình duyệt hỗ trợ cho <picture>. Tuy nhiên, bạn có thể chọn sử dụng Picturefill 1.2 nếu "no-js" là điều bắt buộc đối với bạn.

Yêu cầu khác của Picturefill là hỗ trợ Media Query, để cho phép truy vấn trong thuộc tính media. Tất cả các trình duyệt hiện đại đều hỗ trợ Media Query, chỉ có IE8 và thấp hơn là không hỗ trợ với một lượng người dùng còn lại rất nhỏ.

Phát sinh thêm các yêu cầu HTTP

Trong các trình duyệt có hỗ trợ srcset, nhưng chưa hỗ trợ picture, có thể tên tập tin được chỉ định trong phần tử img dự phòng có thể được yêu cầu trước tiên khi một hình ảnh phù hợp hơn từ các phần tử source được xác định.

Đây chỉ là một vấn đề tạm thời và sẽ biến mất sau khi picture được nạp.

Tìm hiểu thêm

  • Đọc thêm về Picturefill 2.0 và tải về cho dự án của bạn trên trang Picturefill
  • Đọc thông tin đầy đủ về phần tử <picture> từ responsiveimages.org.

Hãy thử <picture> trong dự án của bạn ngay hôm nay và hãy xem bạn nghĩ gì về nó!

Rating: 
5
Average: 5 (1 vote)