Bài trước: Web front-end (14) - HTML - Hình ảnh_svg
-----
1.1.1
Hiển thị ảnh linh hoạt
Trong tiếng Anh, người ta gọi việc hiển thị ảnh linh hoạt,
hay ảnh tùy chỉnh là responsive image.
Responsive (tính từ): có nghĩa là khả năng thích ứng, có
tính linh hoạt, tùy chỉnh (adapt).
Trong lĩnh vực web, responsive là khả năng trang web có thể tự
thay đổi giao diện (gồm nội dung và bố cục – content and layout) tùy theo kích
thước màn hình. Ý tưởng là bạn sẽ viết mã nguồn sao cho, ứng với mỗi thiết bị
duyệt web, như điện thoại (smartphone), máy tính bảng (tablet), máy tính, hay tivi
thì trang web sẽ luôn có giao diện phù hợp, đẹp, dễ đọc.
Ví dụ, với hình ảnh, nếu người dùng đang sử dụng màn hình nhỏ,
mà trang web lại tải về một hình ảnh lớn thì sẽ làm chậm quá trình hiển thị,
lãng phí tài nguyên thiết bị; ngược lại nếu người dùng đang sử dụng màn hình lớn
mà lại tải về một hình ảnh nhỏ, độ phân giải thấp thì sẽ làm cho hình ảnh bị mờ,
không đẹp.
Kỹ thuật hay được sử dụng để tạo ra trang web có khả năng
tùy chỉnh là dùng CSS, JavaScript hoặc xử lý bên phía server. Tuy nhiên, phần
này không đề cập tới việc làm cho cả trang web có tính chất tùy chỉnh, mà chỉ tập
trung vào việc sử dụng HTML, giúp cho hình ảnh có tính chất tùy chỉnh. Ý tưởng là:
chúng ta sẽ chuẩn bị nhiều loại hình ảnh ứng với các kích thước màn hình khác
nhau; khi hiển thị trang web, trình duyệt sẽ tự động chọn hình ảnh cho phù hợp,
dựa vào các yếu tố như kích thước, độ phân giải của màn hình; tốc độ đường truyền,
có lưu bộ đệm (cache) hay không.
Để có hình ảnh tùy chỉnh, cần đáp ứng bốn tình huống sau:
– Cung cấp ảnh chất lượng (dung lượng cao) cho các màn hình
có độ phân giải (resolution) cao
– Với mỗi ảnh, chuẩn bị nhiều tập tin với kích thước
(dimension) khác nhau, để dùng cho mỗi kích thước màn hình
– Cung cấp nhiều phiên bản của một ảnh, với nội dung và kiểu
dáng (portrait, landscape) khác nhau
– Cung cấp nhiều định dạng (format) khác nhau của một ảnh, để
trình duyệt lựa chọn cho phù hợp.
Hiển thị ảnh cho màn
hình có độ phân giải cao
Mọi thứ bạn thấy trên màn hình đều được tạo ra từ các ô màu,
hình vuông, kích thước rất nhỏ, gọi là điểm ảnh hay phần tử ảnh (picture
element), thường gọi là pixel. Các pixel do thiết bị tạo ra, nên gọi là device
pixel (hoặc hardware pixel, physical pixel).
Trên các màn hình hiện tại, số device pixel trên một inch có
thể là 72, 96, 109, 160, 326, hoặc cao hơn.
Số device pixel trên một inch gọi là độ phân giải của màn
hình (pixel per inch), được gọi tắt là ppi.
Ảnh có định dạng kiểu bitmap (jpeg, png, gif) cũng được tạo
ra từ các phần tử ảnh (pixel), các pixel được tổ chức theo kiểu lưới (grid).
Trước đây, kích thước của pixel trên ảnh (hoặc pixel CSS) bằng
với kích thước pixel trên thiết bị, nghĩa là kích thước của 2 loại pixel có tỉ
lệ là 1:1. Khi đó, một ảnh có độ rộng 100 pixel sẽ được đặt vừa khít trên 100
pixel của thiết bị. Mọi chuyện có vẻ đơn giản!
Device-pixel-ratios
Tuy nhiên, các thiết bị hiện nay có độ phân giải ngày càng
cao, nghĩa là số pixel trên một inch ngày càng lớn (kích thước một pixel ngày
càng nhỏ, nhìn ảnh mịn hơn), nếu đặt ảnh vào màn hình theo tỉ lệ 1:1 thì sẽ thấy
ảnh bị thu nhỏ lại. Bạn thử tưởng tượng, bình thường 100 pixel ảnh sẽ tạo được
một khối ảnh dài một inch trên màn hình, nhưng cũng 100 pixel ảnh ấy, bây giờ
chỉ tạo được một khối ảnh có chiều dài 0.3 inch trên màn hình thôi, nghĩa là
kích thước của ảnh trên màn hình đã giảm đi gần ba lần.
Để giải quyết tình trạng trên, các thiết bị sử dụng thêm một
đơn vị đo khác gọi là pixel-tham-chiếu (reference pixel) hay pixel CSS. Đơn vị
đo này được sử dụng trong quá trình hiển thị nội dung ra trình duyệt (layout).
Pixel-tham-chiếu còn có tên gọi khác là point (PT) trong
iOS, hoặc device independent pixel (DP, DiP) trong Android hoặc CSS pixel trong
CSS.
Ví dụ, iPhone 8 có kích thước màn hình là 750 x 1334 (device
pixel), nhưng nó lại dùng lưới-hiển-thị (layout grid), có kích thước là 375 x
667 (pixel-tham-chiếu). Nghĩa là tỉ lệ giữa số điểm ảnh trên thiết bị và số điểm
ảnh trên lưới-hiển-thị là 2:1 (hay 2x); hay nói cách khác, một điểm ảnh trên lưới-hiển-thị
sẽ phủ lên 2 điểm ảnh trên màn hình thiết bị. Vậy, một cái hộp có độ rộng 100
pixel trong lưới-hiển-thị khi xuất hiện trên màn hình iPhone 8 sẽ được đặt
trong 200 pixel. Tương tự, iPhone X có kích thước màn hình tính theo device
pixel là 1125 x 2436, dùng lưới-hiển-thị là 375 x 812. Vậy, tỉ lệ điểm ảnh giữa
màn hình thiết bị và lưới-hiển-thị là
3:1 (hay 3x); nghĩa là một điểm ảnh trên lưới-hiển-thị sẽ phủ lên 3 điểm ảnh trên
màn hình. Kết quả là một cái hộp có độ rộng 100 pixel trong lưới-hiển-thị khi xuất
hiện trên màn hình iPhone X sẽ được đặt trong 300 pixel.
Tỉ lệ giữa điểm ảnh của thiết bị và điểm ảnh của lưới-hiển-thị
được gọi là device-pixel-ratios. Với
các thiết bị cầm tay, device-pixel-ratios thường là 1.325x, 1.5x, 1.7x, 2.4x,
3x, thậm chí 4.x (ký hiệu ‘x’ được ngầm hiểu là device-pixel-ratios, gọi là
x-descriptor).
Xem hình minh họa
về device-pixel-ratios,
Kết luận rút ra ở
đây là nếu bạn muốn hiển thị một ảnh có độ rộng 200px trên một thiết bị có
device-pixel-ratios là 1x thì bạn cần chuẩn bị một ảnh 200px, nhưng nếu hiển thị
trên các thiết bị có device-pixel-ratios là 2x, 3x, thì bạn phải chuẩn bị ảnh
có độ rộng là 400px và 600px tương ứng, nếu không ảnh sẽ bị mờ. Như vậy,
tùy theo độ phân giải của màn hình, bạn cần lựa chọn ảnh phù hợp để tải xuống
thiết bị.
Bạn có thể xem giá trị device-pixel-ratio của một số thiết bị
bằng cách sau:
– Mở trình duyệt web
– Mở Developer tools (mục 1-hình minh họa)
– Sử dụng nút “lựa chọn thiết bị” để xem kết quá trên nhiều
thiết bị khác nhau (mục 2, 3).
– Tại tab Console (mục 4), nhập vào lệnh (JavaScript) console.log(window.devicePixelRatio) (mục 5),
bấm Enter để xem kết quả.
Xem hình minh họa.
Thuộc tính srcset
Để lựa chọn ảnh phù hợp cho từng độ phân giải của màn hình,
bạn sẽ sử dụng thuộc tính srcset cùng với phần tử img. Sử dụng thuộc tính
srcset để liệt kê một danh sách các tập tin ảnh, khi thực thi mã HTML, trình
duyệt sẽ lựa chọn ảnh phù hợp từ danh sách này.
Giá trị của thuộc tính srcset gồm các cặp image-URL và
x-descriptor, mỗi cặp ngăn cách nhau bằng dấu phẩy (,). Ví dụ:
srcset="image-URL1
#x1, image-URL2 #x2"
Trong phần tử img, vẫn có thuộc tính src, đây là đường dẫn của
ảnh cho trường hợp giá trị device-pixel-ratios của thiết bị là 1x. Thuộc tính
alt cũng bắt buộc phải có. Ví dụ,
<img
src="image-URL" alt="" srcset="image-URL1 #x1,
image-URL2 #x2">
Ví dụ sau sẽ hiển thị ảnh có tên là turkey, rộng 200px trên
thiết bị. Nếu màn hình thiết bị ở chế độ phân giải chuẩn, tức
device-pixel-ratios là 1x, thì sẽ hiển thị ảnh turkey-200px.jpg. Nếu màn hình
có độ phân giải cao hơn thì sẽ hiển thị ảnh turkey-400px.jpg cho trường hợp
device-pixel-ratios là 2x hoặc hiển thị ảnh turkey-600px.jpg cho trường hợp device-pixel-device
là 3x.
<img src="/images/turkey-200px.jpg" alt=""
srcset="/images/turkey-400px.jpg 2x, /images/turkey-600px.jpg 3x" >
Có thể viết lại mã nguồn cho dễ nhìn,
<img
src="/images/turkey-200px.jpg" alt=""
srcset="/images/turkey-400px.jpg 2x,
/images/turkey-600px.jpg 3x" >
Khi nào thì nên dùng
x-descriptor
Dựa vào giá trị của x-descriptor, trình duyệt sẽ kiểm tra độ
phân giải của màn hình để lựa chọn ảnh phù hợp, mà nó không quan tâm tới kích
thước của màn hình (dài, rộng) cũng như kích thước của cửa sổ trình duyệt.
Vì vậy, chỉ nên sử dụng x-descriptor đối với các ảnh nhỏ, có
kích thước cố định và không ảnh hưởng nhiều đến bố cục chung của trang web, như
logo, biểu tượng mạng xã hội.
Việc chỉ dựa vào độ phân giải của màn hình để lựa chọn ảnh
trong thực tế là chưa tối ưu. Chúng ta có thể sử dụng cách khác là lựa chọn ảnh
dựa vào kích thước của màn hình, với màn hình nhỏ thì hiển thị ảnh nhỏ, màn
hình lớn thì hiển thị ảnh lớn.
Phần tiếp theo sẽ tìm hiểu về w-descriptor, để hiển thị ảnh
theo kích thước của màn hình.
w-descriptor
Để trang web có khả năng tự lựa chọn ảnh theo kích thước của
cửa sổ trình duyệt (browser viewport) hay kích thước của màn hình (screen) (từ
đây gọi chung là cửa sổ trình duyệt) chúng ta sẽ sử dụng thuộc tính srcset kết
hợp với giá trị w-descriptor. w-descriptor là độ rộng của cửa sổ tính bằng
pixel (actual pixel width). Kĩ thuật này được gọi là lựa chọn hình ảnh theo
kích thước khung nhìn (viewport-based selection).
Chúng ta có thể sử dụng lệnh của JavaScript để xem kích thước
hiện tại của cửa sổ trình duyệt. Mở cửa sổ Developer tools, chọn tab Console,
nhập vào lệnh sau:
console.log(Math.max(document.documentElement.clientWidth
|| 0, window.innerWidth || 0))
Lệnh trên sẽ xuất ra độ rộng của màn hình, đơn vị là pixel. Bạn
có thể thu nhỏ màn hình, chạy lại lệnh để xem kết quả. Xem hình minh họa.
Khi dịch mã nguồn để hiển thị trang web, trình duyệt sẽ kiểm
tra độ rộng của nó, so khớp với giá trị w-descriptor trong thuộc tính srcset để
lựa chọn hình ảnh cho phù hợp.
Ví dụ sau đưa ra bốn hình ảnh, ứng với bốn kích thước của cửa
sổ trình duyệt, tùy theo độ rộng của màn hình, hình ảnh tương ứng sẽ được hiển
thị. Ví dụ: màn hình rộng 480px (hoặc nhỏ hơn) thì ảnh strawberries-480.jpg sẽ
hiển thị; màn hình rộng 960px (hoặc nhỏ hơn) thì ảnh strawberries-960.jpg sẽ hiển
thị. Chữ “w” đằng sau các con số là viết tắt của w-descriptor (width
descriptor), nghĩa là độ rộng.
<img srcset="strawberries-480.jpg 480w,
strawberries-960.jpg 960w,
strawberries-1280.jpg 1280w,
strawberries-2400.jpg 2400w">
Lúc chạy để kiểm tra đoạn mã trên, bạn nhớ tắt chế độ “lưu ảnh
bộ nhớ đệm” (Disable cache) của trình duyệt, kết quả sẽ chính xác hơn. Để tắt
chế độ “lưu ảnh bộ đệm”, trong cửa sổ Developer tools, tab Network, bỏ dấu chọn
ở mục Disable cache.
Sử dụng thuộc tính
sizes
Khi sử dụng giá trị w-descriptor thì bạn cần sử dụng thuộc
tính sizes để báo cho trình duyệt biết ảnh sẽ chiếm bao nhiêu % kích thước của
cửa sổ trình duyệt. Mục đích của việc này là để giúp trình duyệt có thông tin về
kích thước ảnh sẽ hiển thị trên trang, nhằm tăng tốc độ xây dựng layout.
Ví dụ sau sẽ luôn hiển thị banner chiếm 100% kích thước cửa
sổ trình duyệt,
<img src="strawberries-640.jpg"
alt="baskets of ripe strawberries"
srcset="strawberries-480.jpg 480w,
strawberries-960.jpg 960w,
strawberries-1280.jpg 1280w,
strawberries-2400.jpg 2400w"
sizes="100vw">
Đơn vị đo của sizes là vw (viewport width), 100vw tương
đương với 100%, 50vw tương đương 50% kích thước cửa sổ trình duyệt. Ví dụ sau sẽ
hiển thị ảnh chiếm 50% cửa sổ trình duyệt,
<img src="strawberries-640.jpg"
alt="baskets of ripe strawberries"
srcset="strawberries-480.jpg 480w,
strawberries-960.jpg 960w,
strawberries-1280.jpg 1280w,
strawberries-2400.jpg 2400w"
sizes="50vw">
Thuộc tính sizes có thể dùng ở dạng phức tạp hơn, tùy theo độ
rộng của cửa sổ trình duyệt để lựa chọn giá trị size tương ứng, ví dụ,
<img src="strawberries-640.jpg" alt="baskets of ripe strawberries"
srcset="strawberries-240.jpg 240w,
strawberries-480.jpg 480w,
strawberries-672.jpg 672w"
sizes="(max-width: 480px) 100vw,
(max-width: 960px) 70vw,
240px">
Ở đoạn mã trên, nếu độ rộng cửa sổ trình duyệt bằng hoặc nhỏ
hơn 480px thì hiển thị 100% độ rộng của cửa sổ, từ 481px đến 960px thì hiển thị
70%, các trường hợp còn lại hiển thị ảnh với độ rộng đúng bằng 240px.
Art direction (phần tử
picture)
Ở các phần trên, chúng ta đã thực hiện lựa chọn hình ảnh dựa
vào độ phân giải của màn hình và kích thước của cửa sổ trình duyệt. Cả hai trường
hợp này các ảnh chỉ khác nhau ở kích thước, trong khi nội dung của ảnh không
thay đổi.
Trong một số trường hợp, việc thay đổi kích thước ảnh không
có nhiều ý nghĩa, ví dụ một ảnh lớn với nhiều chi tiết, nếu hiển thị ở màn hình
rộng thì bạn có thể nhìn rõ các chi tiết; tuy nhiên, khi hiển thị ở màn hình nhỏ
thì bạn không thể phân biệt được các chi tiết, hiệu quả của hình ảnh không cao.
Trong trường hợp này, bạn chỉ muốn hiển thị một điểm nhấn nào đó trong ảnh. Hoặc
bạn cũng muốn hiển thị ảnh ở dạng đứng (portrait) và dạng nằm ngang (landscape)
là hai ảnh khác nhau.
Ví dụ dưới đây là ảnh ở màn hình rộng (nguồn lấy từ tài liệu
tham khảo [1]),
Tuy nhiên, khi hiển thị ở màn hình nhỏ thì rất mờ nhạt (hình
bên trái), và hình ấn tượng hơn nhờ có điểm nhấn (hình bên phải),
Để chọn ảnh theo độ rộng của cửa sổ trình duyệt, bạn sử dụng
phần tử picture với cú pháp sau,
<picture>
<source media="(min-width: 1024px)" srcset="icecream-large.jpg">
<source media="(min-width: 760px)" srcset="icecream-medium.jpg">
<img src="icecream-small.jpg" alt="hand holding ice cream cone and
text that reads Savor the Summer">
</picture>
Ở đoạn mã trên, nếu cửa sổ trình duyệt có kích thước từ
1024px trở lên thì dùng ảnh icecream-large.jpg, nếu cửa sổ trình duyệt có kích
thước từ 760 px tới 1023px thì dùng ảnh icecream-medium.jpg, nhỏ hơn thì dùng
icecream-small.jpg.
Tóm lại để hiển thị hình ảnh linh hoạt bằng HTML, bạn có thể
sử dụng thuộc tính srcset, sizes và phần tử picture.
1.1.2 Xem và đọc thêm
– [1] Jenifer Niederst
Robbins, Learning Web Design,
O’Reilly, 2018, trang 131 – 162.
– [view] Add links: https://www.youtube.com/watch?v=kUMe1FH4CHE&t=5438s
– Pixel: https://en.wikipedia.org/wiki/Pixel
-----