Tìm hiểu về Responsive Image

Tìm hiểu về Responsive Image

Responsive Image là 1 trong những cách cải thiện tốc độ load web/app của bạn 1 cách đáng kể, tuy nhiên không phải lập trình viên nào cũng biết, hôm nay hãy cùng mình đi tìm hiểu về kĩ thuật này nhé. :D

Responsive Image là gì ?

Mục đích chính của responsive image là “đúng người đúng thời điểm” à không “đúng hình ảnh đúng màn hình” nhằm tối ưu tốc độ cho website tránh việc phải load những ảnh kích thước lớn hơn cần thiết với các màn hình nhỏ.

Ví dụ như việc: Với 1 bức ảnh có kích thước 1MB, nếu chạy trên bản desktop hay các thiết bị lớn thì không phải là vấn đề gì to tát lắm, tốc độ vẫn không ảnh hưởng quá nhiều, nhưng nếu đối với những thiết bị nhỏ hơn như điện thoại, việc phải load 1 ảnh có kích thước 1MB sẽ có ảnh hưởng nhất định đến tốc độ load trang web làm giảm điểm của website/app của bạn trong mắt người dùng.

Đây là bài toán mà những web developers như chúng ta sẽ gặp và phải giải quyết nó.

Vậy sử dụng responsive image khi nào là hợp lí?

Có 3 trường hợp phổ biến nhất mà ở đó responsive image sẽ cực kì hữu ích trong việc giảm thiểu thời gian loading và làm cho web/app của bạn nhanh hơn đáng kể.

Trường hợp đầu tiên đó chính là: Resolution switching.

Cái này có thể tạm hiểu là giữa các kích thước màn hình khác nhau, như trong ví dụ ở đầu tiên mình chia sẻ.

Với màn hình nhỏ thì đâu cần thiết phải có 1 cái ảnh với kích thước lớn giống như ở màn hình desktop đâu, đúng không?

Thứ hai là: Density switching.

Đây là 1 trường hợp đặc biệt của resolution switching, nhưng cái ta quan tâm ở đây không phải kích thước màn hình mà là mật độ điểm ảnh (pixel density). Pixel density là số điểm ảnh có trên đường chéo 1 inch. Giống như kích thước thì có to, có nhỏ thì ta cũng có những màn hình có mật độ điểm ảnh cao và mật độ điểm ảnh thấp. Ví dụ về màn hình có mật độ điểm ảnh thấp thì có thể kể đến các màn hình PC bình thường, chúng thường được gọi là 1x screen vì tỉ lệ pixel vật lí và pixcel logic của các màn hình này 1:1 – nếu ảnh của chúng ta cao 100 pixel thì nó cũng sẽ sử dụng 100 pixel vật lí trên các màn hình đó. Các màn hình có mật độ điểm ảnh cao có thể kể đến như các điện thoại smart phone hiện nay, hay 1 số các màn hình máy tính, laptop – tiêu biểu như Macbook, các màn hình này thường hiển thị với tỉ lệ 2:1 - ảnh cao 100 pixels sẽ sử dụng 200 pixels vật lí.

Cuối cùng là: Art direction.

Đây là trường hợp khi bạn muốn hiển thị các hình ảnh khác nhau ở các màn hình khác nhau. Cần phân biệt với các trường hợp ở trên đó là: ở các trường hợp ở trên, các hình ảnh chỉ khác nhau về kích thước, nội dung ảnh giống hệt nhau còn ở trường hợp này, các hình ảnh có thể khác nhau hoàn toàn.

Cách thực hiện.

Bây giờ chúng ta sẽ đi vào chi tiết với từng trường hợp.

1: Resolution switching.

Xét đoạn code sau đây:

Trong đoạn code trên, có lẽ sẽ khá mới mẻ với nhiều bạn, vì có thêm 2 thuộc tính mới là srcset và sizes.

Srcset chứa các “danh sách” hình ảnh mà chúng ta cho phép trình duyệt lựa chọn cùng với kích thước của chúng. Mỗi phần tử của danh sách này gồm có: đường dẫn đến hình ảnh và kích thước của chúng, 2 thuộc tính này được đặt cách nhau 1 khoảng trắng. Giữa mỗi phần tử sẽ được ngăn cách bởi dấu “,”. Một chú ý nhỏ ở đây là kích thước này là chiều rộng (width) của ảnh và đơn vị viết của nó là w thay vì px. Trong ví dụ trên, mình có 2 ảnh có kích thước width lần lượt là 1000px300px.

Sizes chứa các media conditions (ví dụ như kích thước màn hình) và kích thước của hình ảnh phù hợp nhất với điều kiện đó. Như trong ví dụ trên thì ta có điều kiện là max-width: 600px (các màn hình có kích thước width <= 600px) thì kích thước phù hợp nhất sẽ là 300px. Bạn có thể tự hỏi sao với 1000px lại không có điều kiện gì bởi vì nó được gọi là default case. Các điều kiện sẽ được xét lần lượt theo tuần tự, nếu điều kiện nào thỏa mãn thì trình duyệt sẽ lựa chọn kích thước tại điều kiện đó và dừng. Trong trường hợp không có điều kiện nào thỏa mãn thì sẽ sử dụng default case.

Một chú ý nho nhỏ đó là với kích thước ở phần sizes này chúng ta có thể sử dụng px, em hay vw nhưng không được sử dụng %

Tóm lại, khi khai báo như vậy, trình duyệt sẽ thực hiện các bước như sau:

Bước 1: Kiểm tra kích thước width của thiết bị

Bước 2: Lần lượt kiểm tra từng điều kiện, gặp điều kiện đúng thì dừng và nhớ kích thước tương ứng với điều kiện này.

Bước 3: Đi 1 lượt các “danh sách” hình ảnh trong srcset và chọn hình ảnh có kích thước gần nhất với kích thước đã nhớ ở Bước 2.

Cụ thể trong ví dụ trên, kết quả sẽ như sau:

Khi kích thước màn hình lớn hơn 600px – cụ thể ở trong ảnh là 1904px thì src của hình ảnh sẽ là: ../nat-1-large.jpg. Tại sao lại như vậy? Vì kích thước màn hình hiện tại có width là 1904px > 600px không thỏa mãn điều kiện đầu nên trình duyệt lấy default case1000px, kích thước của ảnh nat-1-large là kích thước gần nhất với 1000px trong srcset nên sẽ lấy ảnh này.

Tương tự, nếu kích thước của màn hình <= 600px thì hình ảnh sẽ là: nat-1.jpg.

2: Density switching.

Xét đoạn code sau:

Về cơ bản thì không khác resolution switching là bao nhiêu trừ việc lúc này ta không có thuộc tính sizes nữa, và trong srcset thay vì bộ đôi : đường dẫn _ kích thước, giờ ta có bộ đôi đường dẫn _tỉ lệ điểm ảnh. tỉ lệ điểm ảnh ở đây là 1x, 2x, … nx. Hiện tại mới có 1x, 2x,3x mà thôi.

Để có thể test được tốt nhất thì các bạn nên sử dụng Firefox.

Ở các trình duyệt hiện nay trong dev tools có 1 công cụ để chỉnh sửa tỉ lệ pixcel Nó là thuộc tính DPR (device pixel ratio) nằm ở thanh trên cùng như thế này: (Ở Firefox)

Nó là thuộc tính mình gạch chân màu đỏ.

Đây là hình ảnh kết quả của đoạn code trên ở màn hình 2x.

 

Giờ sang 1x xem thế nào nhé.

Các bạn cũng có thể nhận thấy rõ được sự thay đổi rồi đúng không nào. Ở màn hình 1x, ảnh nat-1.jpg với kích thước width  300px sẽ được sử dụng, ở màn hình 2x, ảnh nat-1-large.jpg với kích thước width 1000px  sẽ được sử dụng.

Trường hợp 3: art direction.

Xét đoạn code sau:

art direction, cú pháp sẽ hơi phức tạp hơn 1 chút, khi chúng ta sử dụng thẻ picture, thẻ source kết hợp với thẻ img.

Thẻ source sẽ gồm có 1 thuộc tính media chứa media condition giống như ở ví dụ về resolution switching, các condition này sẽ được kiểm tra để quyết định xem ảnh nào sẽ được sử dụng. Trong trường hợp này, nếu kích thước width của màn hình <= 600px thì phần tử source đầu tiên sẽ được sử dụng. Nếu kích thước width của thiết bị <= 900px thì phần tử source thứ 2 sẽ được sử dụng. Thẻ img cuối cùng ở đây là default case, khi không media condition nào thỏa mãn thì trình duyệt sẽ hiển thị hình ảnh ở thẻ img này. Các bạn chú ý là gặp điều kiện nào thỏa mãn kích thước của màn hình hiện tại thì sẽ dừng luôn và không xét các điều kiện tiếp theo nên khi viết các bạn cần chú ý thứ tự. 

Thuộc tính srcset sẽ chứa đường dẫn của hình ảnh, mỗi thẻ source sẽ có 1 thuộc tính srcset, và mỗi thuộc tính srcset này có thể chứa nhiều hơn 1 đường dẫn – hay nói cách khác chúng ta có thể kết hợp với cả việc xử lí với resolution switching ở đây. Tuy nhiên thường thì chúng ta sẽ không kết hợp lại vì làm như vậy sẽ rất rối.

Kết quả của đoạn code trên sẽ như sau:

Ở đây mình sử dụng 3 hình ảnh khác nhau để các bạn thấy rõ sự khác biệt. Với mỗi kích thước nằm trong 1 khoảng media condition ta sẽ có 1 hình ảnh khác nhau.

Chú  ý là: bạn chỉ nên sử dụng thuộc tính media khi xử lí với art directions, và khi sử dụng media thì không nên sử dụng thêm thuộc tính sizes nữa.

À đến đây có lẽ nhiều bạn sẽ thấy những cách làm trên khá là rắc rối, tại sao chúng ta lại không sử dụng CSS hay JS để làm việc này.

Lí do đơn giản là bởi vì khi trình duyệt load trang thì nó sẽ download toàn bộ các hình ảnh có trong trang trước khi xử lí đến CSS hay JS. Vậy chẳng lẽ bạn chờ nó download xong hình ảnh rồi, trong JS bạn sẽ lấy kích thước màn hình, rồi sau đó quay trở lại thay thế hình ảnh bằng 1 hình ảnh khác phù hợp hơn với kích thước màn hình đó hay sao? Lúc đó thì hình ảnh cũng đã load xong rồi, việc bạn có thay đổi lại hình ảnh 1 lần nữa chỉ là việc “vẽ rắn thêm chân” chẳng có tác dụng gì cả.

Tạm kết, vậy là trên đây mình đã cùng các bạn đi qua các kĩ thuật xử lí responsive image, kĩ thuật này nếu được sử dụng tốt sẽ cải thiện đáng kể tốc độ trang web hay app của bạn. Mong nhận được các ý kiến đóng góp từ các bạn nếu có bổ sung / sai sót. Thân