Hình ảnh thường là tài nguyên nặng nhất và phổ biến nhất trên web. Do đó, việc tối ưu hoá hình ảnh có thể cải thiện đáng kể hiệu suất trên trang web của bạn. Trong hầu hết các trường hợp, việc tối ưu hoá hình ảnh có nghĩa là giảm thời gian mạng bằng cách gửi ít byte hơn, nhưng bạn cũng có thể tối ưu hoá số lượng byte được gửi đến người dùng bằng cách phân phát hình ảnh có kích thước phù hợp với thiết bị của người dùng.
Bạn có thể thêm hình ảnh vào trang bằng cách sử dụng các phần tử <img>
hoặc <picture>
, hoặc thuộc tính CSS background-image
.
Kích thước hình ảnh
Việc tối ưu hoá đầu tiên mà bạn có thể thực hiện khi sử dụng tài nguyên hình ảnh là hiển thị hình ảnh ở kích thước chính xác. Trong trường hợp này, thuật ngữ kích thước đề cập đến kích thước của hình ảnh. Nếu không có biến số nào khác, hình ảnh hiển thị trong vùng chứa 500 pixel x 500 pixel sẽ có kích thước tối ưu là 500 pixel x 500 pixel. Ví dụ: nếu bạn sử dụng hình ảnh vuông có kích thước 1.000 pixel, tức là hình ảnh đó lớn gấp đôi so với kích thước cần thiết.
Tuy nhiên, có nhiều biến số liên quan đến việc chọn kích thước hình ảnh phù hợp, khiến việc chọn kích thước hình ảnh phù hợp trong mọi trường hợp trở nên khá phức tạp. Năm 2010, khi iPhone 4 ra mắt, độ phân giải màn hình (640x960) gấp đôi so với iPhone 3 (320x480). Tuy nhiên, kích thước vật lý của màn hình iPhone 4 vẫn gần như tương đương với iPhone 3.
Việc hiển thị mọi thứ ở độ phân giải cao hơn sẽ khiến văn bản và hình ảnh nhỏ hơn đáng kể – chính xác là bằng một nửa kích thước trước đây. Thay vào đó, 1 pixel trở thành 2 pixel thiết bị. Đây được gọi là tỷ lệ pixel của thiết bị (DPR). iPhone 4 (và nhiều mẫu iPhone được phát hành sau đó) có DPR là 2.
Quay lại ví dụ trước, nếu thiết bị có DPR là 2 và hình ảnh được hiển thị trong một vùng chứa 500 pixel x 500 pixel, thì hình ảnh vuông 1000 pixel (được gọi là kích thước nội tại) hiện là kích thước tối ưu. Tương tự, nếu thiết bị có DPR là 3, thì hình ảnh vuông 1500 pixel sẽ là kích thước tối ưu.
srcset
Phần tử <img>
hỗ trợ thuộc tính srcset
, cho phép bạn chỉ định danh sách các nguồn hình ảnh có thể dùng cho trình duyệt. Mỗi nguồn hình ảnh được chỉ định phải bao gồm URL hình ảnh và một giá trị mô tả mật độ điểm ảnh hoặc chiều rộng.
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
Đoạn mã HTML ở trên sử dụng bộ mô tả mật độ pixel để gợi ý cho trình duyệt sử dụng image-500.png
trên các thiết bị có DPR là 1, image-1000.jpg
trên các thiết bị có DPR là 2 và image-1500.jpg
trên các thiết bị có DPR là 3.
Mặc dù tất cả những điều này có vẻ đơn giản, nhưng DPR của màn hình không phải là yếu tố duy nhất cần cân nhắc khi chọn hình ảnh tối ưu cho một trang nhất định. Bố cục của trang là một yếu tố khác cần cân nhắc.
sizes
Giải pháp trước đây chỉ hoạt động nếu bạn hiển thị hình ảnh ở cùng kích thước pixel CSS trên tất cả các khung hiển thị. Trong nhiều trường hợp, bố cục của một trang (và kích thước của vùng chứa) sẽ thay đổi tuỳ thuộc vào thiết bị của người dùng.
Thuộc tính sizes
cho phép bạn chỉ định một tập hợp kích thước nguồn, trong đó mỗi kích thước nguồn bao gồm một điều kiện về nội dung nghe nhìn và một giá trị. Thuộc tính sizes
mô tả kích thước hiển thị dự kiến của hình ảnh tính bằng pixel CSS. Khi kết hợp với các bộ mô tả chiều rộng srcset
, trình duyệt có thể chọn nguồn hình ảnh phù hợp nhất cho thiết bị của người dùng.
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
Trong đoạn mã HTML ở trên, thuộc tính srcset
chỉ định danh sách các hình ảnh mà trình duyệt có thể chọn, được phân tách bằng dấu phẩy. Mỗi đề xuất trong danh sách bao gồm URL của hình ảnh, theo sau là một cú pháp biểu thị chiều rộng vốn có của hình ảnh. Kích thước thực tế của hình ảnh là kích thước của hình ảnh đó. Ví dụ: một giá trị mô tả 1000w
cho biết chiều rộng vốn có của hình ảnh là 1000 pixel.
Dựa vào thông tin này, trình duyệt sẽ đánh giá điều kiện về nội dung nghe nhìn trong thuộc tính sizes
và trong trường hợp này, trình duyệt được hướng dẫn rằng nếu chiều rộng khung hiển thị của thiết bị vượt quá 768 pixel, thì hình ảnh sẽ hiển thị ở chiều rộng 500 pixel. Trên các thiết bị nhỏ hơn, hình ảnh sẽ hiển thị ở 100vw
hoặc chiều rộng đầy đủ của khung hiển thị.
Sau đó, trình duyệt có thể kết hợp thông tin này với danh sách các nguồn hình ảnh srcset
để tìm ra hình ảnh tối ưu. Ví dụ: nếu người dùng đang sử dụng thiết bị di động có chiều rộng màn hình là 320 pixel với DPR là 3, thì hình ảnh sẽ hiển thị ở 320 CSS pixels x 3 DPR = 960 device pixels
. Trong ví dụ này, hình ảnh có kích thước gần nhất sẽ là image-1000.jpg
với chiều rộng tự nhiên là 1.000 pixel (1000w
).
Định dạng tệp
Các trình duyệt hỗ trợ nhiều định dạng tệp hình ảnh. Các định dạng hình ảnh hiện đại như WebP và AVIF có thể nén tốt hơn so với PNG hoặc JPEG, giúp giảm kích thước tệp hình ảnh và do đó giảm thời gian tải xuống. Bằng cách phân phát hình ảnh ở định dạng hiện đại, bạn có thể giảm thời gian tải của một tài nguyên, điều này có thể dẫn đến Thời gian hiển thị nội dung lớn nhất (LCP) thấp hơn.
WebP là một định dạng được hỗ trợ rộng rãi và hoạt động trên tất cả các trình duyệt hiện đại. WebP thường có khả năng nén tốt hơn so với JPEG, PNG hoặc GIF, đồng thời cung cấp cả nén có tổn hao và nén không tổn hao. WebP cũng hỗ trợ độ trong suốt của kênh alpha ngay cả khi sử dụng tính năng nén có tổn hao – một tính năng mà bộ mã hoá và giải mã JPEG không cung cấp.
AVIF là một định dạng hình ảnh mới hơn và mặc dù không được hỗ trợ rộng rãi như WebP, nhưng định dạng này vẫn được hỗ trợ khá tốt trên các trình duyệt. AVIF hỗ trợ cả tính năng nén có tổn hao và không tổn hao, đồng thời các thử nghiệm cho thấy mức tiết kiệm lớn hơn 50% khi so sánh với JPEG trong một số trường hợp. AVIF cũng cung cấp các tính năng Gam màu rộng (WCG) và Dải động cao (HDR).
Nén
Đối với hình ảnh, có hai loại nén:
Phương pháp nén có tổn hao hoạt động bằng cách giảm độ chính xác của hình ảnh thông qua lượng tử hoá và thông tin màu bổ sung có thể bị loại bỏ bằng cách sử dụng lấy mẫu phụ sắc độ. Phương pháp nén có tổn hao hiệu quả nhất đối với những hình ảnh có mật độ cao với nhiều nhiễu và màu sắc – thường là ảnh hoặc hình ảnh có nội dung tương tự. Điều này là do các hiện tượng giả tạo do quá trình nén mất dữ liệu tạo ra ít có khả năng bị phát hiện trong những hình ảnh chi tiết như vậy. Tuy nhiên, phương pháp nén mất dữ liệu có thể kém hiệu quả hơn với những hình ảnh có các cạnh sắc nét như hình vẽ đường nét, các chi tiết tương tự hoặc văn bản. Bạn có thể áp dụng tính năng nén có tổn hao cho hình ảnh JPEG, WebP và AVIF.
Tính năng nén không tổn hao giúp giảm kích thước tệp bằng cách nén hình ảnh mà không làm mất dữ liệu. Nén không mất dữ liệu mô tả một pixel dựa trên sự khác biệt so với các pixel lân cận. Phương pháp nén không tổn hao được dùng cho các định dạng hình ảnh GIF, PNG, WebP và AVIF.
Bạn có thể nén hình ảnh bằng Squoosh, ImageOptim hoặc một dịch vụ tối ưu hoá hình ảnh. Khi nén, không có chế độ cài đặt chung nào phù hợp với mọi trường hợp. Phương pháp được đề xuất là thử nghiệm với các mức nén khác nhau cho đến khi bạn tìm được điểm cân bằng giữa chất lượng hình ảnh và kích thước tệp. Một số dịch vụ tối ưu hoá hình ảnh nâng cao có thể tự động thực hiện việc này cho bạn, nhưng có thể không phù hợp với ngân sách của một số người dùng.
Phần tử <picture>
Phần tử <picture>
giúp bạn linh hoạt hơn khi chỉ định nhiều đề xuất hình ảnh:
<picture>
<source type="image/avif" srcset="image.avif">
<source type="image/webp" srcset="image.webp">
<img
alt="An image"
width="500"
height="500"
src="/image.jpg"
>
</picture>
Khi sử dụng(các) phần tử <source>
trong phần tử <picture>
, bạn có thể thêm chế độ hỗ trợ cho hình ảnh AVIF và WebP, nhưng quay lại các định dạng hình ảnh cũ tương thích hơn nếu trình duyệt không hỗ trợ các định dạng hiện đại. Với phương pháp này, trình duyệt sẽ chọn phần tử <source>
đầu tiên được chỉ định khớp. Nếu có thể hiển thị hình ảnh ở định dạng đó, thì nó sẽ sử dụng hình ảnh đó. Nếu không, trình duyệt sẽ chuyển sang phần tử <source>
được chỉ định tiếp theo. Trong đoạn mã HTML ở trên, định dạng AVIF được ưu tiên hơn định dạng WebP, quay lại định dạng JPEG nếu không có định dạng AVIF hoặc WebP nào được hỗ trợ.
Phần tử <picture>
yêu cầu phần tử <img>
được lồng bên trong phần tử đó. Các thuộc tính alt
, width
và height
được xác định trên <img>
và được dùng bất kể bạn chọn <source>
nào.
Phần tử <source>
cũng hỗ trợ các thuộc tính media
, srcset
và sizes
. Tương tự như ví dụ về <img>
trước đó, các giá trị này cho trình duyệt biết nên chọn hình ảnh nào trên các khung hiển thị khác nhau.
<picture>
<source
media="(min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
Thuộc tính media
nhận một điều kiện về nội dung nghe nhìn. Trong ví dụ trước, DPR của thiết bị được dùng làm điều kiện về nội dung nghe nhìn. Mọi thiết bị có DPR lớn hơn hoặc bằng 1,5 sẽ sử dụng phần tử <source>
đầu tiên. Phần tử <source>
cho trình duyệt biết rằng trên các thiết bị có khung hiển thị rộng hơn 768 pixel, ứng cử viên hình ảnh được chọn sẽ hiển thị ở chiều rộng 500 pixel. Trên các thiết bị nhỏ hơn, thành phần này sẽ chiếm toàn bộ chiều rộng của khung hiển thị. Bằng cách kết hợp các thuộc tính media
và srcset
, bạn có thể kiểm soát chính xác hơn hình ảnh cần sử dụng.
Điều này được minh hoạ trong bảng sau, trong đó một số chiều rộng khung hiển thị và tỷ lệ pixel trên thiết bị được đánh giá:
Chiều rộng khung hiển thị (pixel) | 1 DPR | 1,5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000.jpg |
480 | 500.jpg | 500.jpg | 1000.jpg | 1500.jpg |
560 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
Các thiết bị có DPR là 1 sẽ tải hình ảnh image-500.jpg
xuống, bao gồm cả hầu hết người dùng máy tính (những người xem hình ảnh ở kích thước bên ngoài là 500 pixel chiều rộng). Mặt khác, người dùng thiết bị di động có DPR là 3 sẽ tải một image-1500.jpg
có kích thước lớn hơn (cùng một hình ảnh được dùng trên các thiết bị máy tính có DPR là 3).
<picture>
<source
media="(min-width: 561px) and (min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<source
media="(max-width: 560px) and (min-resolution: 1.5x)"
srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
Trong ví dụ này, phần tử <picture>
được điều chỉnh để thêm một phần tử <source>
khác nhằm sử dụng các hình ảnh khác nhau cho các thiết bị có màn hình rộng với DPR cao:
Chiều rộng khung hiển thị (pixel) | 1 DPR | 1,5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 1000-sm.jpg | 1000-sm.jpg |
480 | 500.jpg | 500.jpg | 1000-sm.jpg | 1500-sm.jpg |
560 | 500.jpg | 1000-sm.jpg | 1000-sm.jpg | 1500-sm.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
Với truy vấn bổ sung này, bạn có thể thấy rằng image-1000-sm.jpg
và image-1500-sm.jpg
xuất hiện trên các khung hiển thị nhỏ. Thông tin bổ sung này cho phép bạn nén hình ảnh hơn nữa, vì các cấu phần nén không xuất hiện rõ ở kích thước và mật độ đó, đồng thời không làm ảnh hưởng đến chất lượng hình ảnh trên thiết bị máy tính.
Ngoài ra, bằng cách điều chỉnh các thuộc tính srcset
và media
, bạn có thể tránh phân phát hình ảnh lớn trên các khung hiển thị nhỏ:
<picture>
<source
media="(min-width: 561px)"
srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
<source
media="(max-width: 560px)"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
Trong đoạn mã HTML trước đó, các giá trị mô tả chiều rộng đã bị xoá để thay thế bằng các giá trị mô tả tỷ lệ pixel của thiết bị. Hình ảnh được phân phát trên thiết bị di động bị giới hạn ở /image-500.jpg
hoặc /image-1000.jpg
, ngay cả trên những thiết bị có DPR là 3.
Cách quản lý độ phức tạp
Khi làm việc với hình ảnh thích ứng, bạn có thể thấy nhiều biến thể kích thước và định dạng khác nhau cho mỗi hình ảnh. Trong ví dụ trước, các biến thể cho từng kích thước được dùng, nhưng không bao gồm AVIF và WebP. Bạn nên có bao nhiêu biến thể? Giống như nhiều vấn đề kỹ thuật khác, câu trả lời thường là "tuỳ thuộc vào".
Mặc dù bạn có thể muốn có nhiều biến thể nhất có thể để mang lại kết quả phù hợp nhất, nhưng mỗi biến thể hình ảnh bổ sung đều có chi phí và làm giảm hiệu quả sử dụng bộ nhớ đệm của trình duyệt. Chỉ với một biến thể, mọi người dùng đều nhận được cùng một hình ảnh, vì vậy, hình ảnh này có thể được lưu vào bộ nhớ đệm một cách hiệu quả.
Mặt khác, nếu có nhiều biến thể, mỗi biến thể sẽ yêu cầu một mục nhập khác trong bộ nhớ đệm. Chi phí máy chủ có thể tăng và hiệu suất có thể giảm nếu mục nhập bộ nhớ đệm của biến thể đã hết hạn và hình ảnh cần được tìm nạp lại từ máy chủ gốc.
Ngoài ra, kích thước của tài liệu HTML sẽ tăng lên với mỗi biến thể. Bạn có thể thấy mình đang vận chuyển nhiều kilobyte HTML cho mỗi hình ảnh.
Phân phát hình ảnh dựa trên tiêu đề yêu cầu Accept
Tiêu đề yêu cầu HTTP Accept
thông báo cho máy chủ biết những loại nội dung mà trình duyệt của người dùng hiểu được. Máy chủ của bạn có thể dùng thông tin này để phân phát định dạng hình ảnh tối ưu mà không cần thêm byte vào các phản hồi HTML.
if (request.headers.accept) {
if (request.headers.accept.includes('image/avif')) {
return reply.from('image.avif');
} else if (request.headers.accept.includes('image/webp')) {
return reply.from('image.webp');
}
}
return reply.from('image.jpg');
Đoạn mã HTML ở trên là phiên bản đơn giản của mã mà bạn có thể thêm vào phần phụ trợ JavaScript của máy chủ để chọn và phân phát định dạng hình ảnh tối ưu.
Nếu tiêu đề yêu cầu Accept
bao gồm image/avif
, thì hình ảnh AVIF sẽ được phân phát. Nếu không, nếu tiêu đề Accept
có chứa image/webp
, thì hình ảnh WebP sẽ được phân phát. Nếu không có điều kiện nào trong số này là đúng, thì hình ảnh JPEG sẽ được phân phát.
Bạn có thể sửa đổi các phản hồi dựa trên nội dung của tiêu đề yêu cầu Accept
trong hầu hết mọi loại máy chủ web. Ví dụ: bạn có thể viết lại các yêu cầu về hình ảnh trên máy chủ Apache dựa trên tiêu đề Accept
bằng cách sử dụng mod_rewrite
.
Điều này không khác với hành vi mà bạn sẽ thấy trên Mạng phân phối nội dung (CDN) hình ảnh. CDN hình ảnh là giải pháp tuyệt vời để tối ưu hoá hình ảnh và gửi định dạng tối ưu dựa trên thiết bị và trình duyệt của người dùng.
Điều quan trọng là bạn phải tìm được sự cân bằng, tạo ra một số lượng đề xuất hình ảnh hợp lý và đo lường tác động đối với trải nghiệm người dùng. Các hình ảnh khác nhau có thể mang lại kết quả khác nhau và các hoạt động tối ưu hoá được áp dụng cho từng hình ảnh sẽ phụ thuộc vào kích thước của hình ảnh đó trong trang và thiết bị mà người dùng đang sử dụng. Ví dụ: một hình ảnh chính có chiều rộng đầy đủ có thể yêu cầu nhiều biến thể hơn so với hình ảnh thu nhỏ trên trang thông tin sản phẩm của trang thương mại điện tử.
Tải từng phần
Bạn có thể yêu cầu trình duyệt tải hình ảnh một cách trì hoãn khi hình ảnh xuất hiện trong khung nhìn bằng cách sử dụng thuộc tính loading
. Giá trị thuộc tính lazy
cho biết trình duyệt không tải hình ảnh xuống cho đến khi hình ảnh nằm trong (hoặc gần) khung hiển thị. Điều này giúp tiết kiệm băng thông, cho phép trình duyệt ưu tiên các tài nguyên cần thiết để hiển thị nội dung quan trọng đã có trong khung nhìn.
decoding
Thuộc tính decoding
cho trình duyệt biết cách giải mã hình ảnh. Giá trị async
cho trình duyệt biết rằng hình ảnh có thể được giải mã không đồng bộ, có thể cải thiện thời gian kết xuất nội dung khác. Giá trị sync
cho trình duyệt biết rằng hình ảnh phải xuất hiện cùng lúc với nội dung khác.
Giá trị mặc định của auto
cho phép trình duyệt quyết định lựa chọn phù hợp nhất cho người dùng.
Bản minh hoạ hình ảnh
Kiểm tra kiến thức của bạn
Định dạng hình ảnh nào hỗ trợ tính năng nén không tổn hao?
Định dạng hình ảnh nào hỗ trợ tính năng nén có tổn hao?
Bộ mô tả chiều rộng (ví dụ: 1000w
) cho trình duyệt biết điều gì về một ảnh ứng cử được chỉ định trong thuộc tính srcset
?
Thuộc tính sizes
cho trình duyệt biết điều gì về phần tử <img>
mà thuộc tính này được áp dụng?
srcset
của phần tử <img>
.
srcset
của phần tử <img>
sẽ được tải, dựa trên kích thước của khung hiển thị hiện tại của người dùng.
Tiếp theo: Hiệu suất video
Mặc dù hình ảnh có thể là loại nội dung nghe nhìn phổ biến nhất được dùng trên web, nhưng đây không phải là loại nội dung duy nhất mà bạn cần lưu ý khi nói đến hiệu suất. Video là một loại nội dung nghe nhìn phổ biến khác được sử dụng trên web và có những điểm cần cân nhắc về hiệu suất riêng. Trong học phần tiếp theo của khoá học này, hãy khám phá một số kỹ thuật tối ưu hoá video và cách tải video một cách hiệu quả.