nicetool.dev logo
#images#performance#frontend

JPEG, PNG, WebP hay AVIF? Chọn định dạng ảnh và mức nén thực sự hiệu quả

Nên dùng định dạng nào cho ảnh chụp, ảnh chụp màn hình và logo, mức chất lượng hợp lý, vì sao giảm kích thước quan trọng hơn đổi định dạng, kèm kết quả đo thực tế khi nén một ảnh chụp giao diện.

7 phút đọc

Hình ảnh thường là phần nặng nhất của một trang web. Với nhiều website, đây cũng là chỗ cải thiện tốc độ dễ nhất: cùng một bức ảnh thường có thể giảm còn một phần ba dung lượng mà không ai nhận ra khác biệt. Cái khó là biết nên chỉnh cái gì. Đổi định dạng, giảm chất lượng hay thu nhỏ kích thước? Bài viết này trả lời bằng vài quy tắc đơn giản và một thí nghiệm nhỏ mà bạn có thể tự làm lại.

Bốn định dạng trong một bảng

Định dạng Kiểu nén Nền trong suốt Hợp nhất với Hỗ trợ trình duyệt
JPEG Mất dữ liệu Không Ảnh chụp, khi không dùng được định dạng khác Mọi nơi
PNG Không mất dữ liệu Có Ảnh chụp màn hình, giao diện, sơ đồ, ảnh có chữ Mọi nơi
WebP Cả hai kiểu Có Gần như mọi thứ, lựa chọn mặc định an toàn Mọi trình duyệt hiện tại (Safari từ bản 14)
AVIF Cả hai kiểu Có Ảnh chụp và ảnh banner lớn, khi bạn mã hóa được Chrome, Firefox, Safari 16+, Edge 121+

Có hai định dạng được cố ý bỏ ra. SVG là lựa chọn đúng cho logo, icon và hình minh họa đơn giản vì nó là ảnh vector, sắc nét ở mọi kích thước. GIF nên được thay thế: một đoạn video ngắn lặp lại (MP4 hoặc WebM) hoặc WebP động thường nhỏ hơn nhiều lần.

Nén mất dữ liệu hay không: quyết định quan trọng nhất

Định dạng không mất dữ liệu (PNG, WebP lossless) lưu chính xác từng điểm ảnh. Chúng nén tốt khi ảnh có nhiều mảng cùng một màu, ví dụ trình soạn code, dashboard hay sơ đồ.

Định dạng mất dữ liệu (JPEG, WebP lossy, AVIF) bỏ bớt những chi tiết mắt khó nhận ra. Chúng rất hợp với ảnh chụp, vốn đầy nhiễu hạt và chuyển màu mượt. Nhưng chúng xử lý kém các cạnh sắc: quanh chữ, bộ mã hóa mất dữ liệu tạo ra những ô vuông mờ và quầng sáng (hiện tượng "ringing").

Vì vậy câu hỏi đầu tiên không phải "dùng định dạng nào" mà là "đây là ảnh chụp hay ảnh đồ họa?"

  • Ảnh chụp, ảnh render hoặc ảnh có kết cấu tự nhiên → nén mất dữ liệu.
  • Ảnh chụp màn hình, biểu đồ, mockup giao diện, ảnh có chữ nhỏ → thử không mất dữ liệu trước, sau đó thử WebP hoặc AVIF mất dữ liệu và kiểm tra phần chữ bằng mắt.

Thí nghiệm với một ảnh chụp màn hình thật

Để kiểm tra các quy tắc trên, mình chụp màn hình một trang của nicetool.dev ở mật độ điểm ảnh 2× (2560×1600 pixel, giống ảnh chụp trên laptop màn hình Retina) và mã hóa theo nhiều cách bằng sharp, thư viện dựa trên libvips mà nhiều CDN ảnh đang dùng:

Phiên bản Dung lượng Tiết kiệm
Ảnh chụp gốc từ trình duyệt (PNG) 253 KB -
PNG, nén tối đa 95 KB 62%
WebP lossless 98 KB 61%
JPEG, chất lượng 80 151 KB 40%
WebP, chất lượng 80 101 KB 60%
AVIF, chất lượng 50 64 KB 75%
PNG, thu nhỏ còn rộng 1280 px 158 KB 38%
WebP chất lượng 80, thu nhỏ còn rộng 1280 px 41 KB 84%

Kết quả có vài điều bất ngờ:

  1. Chỉ lưu lại file PNG đã tiết kiệm 62%. Công cụ chụp màn hình và trình duyệt ghi PNG theo hướng nhanh chứ không theo hướng gọn. Chạy qua một công cụ tối ưu không làm giảm chất lượng chút nào.
  2. JPEG là lựa chọn mất dữ liệu tệ nhất, nặng hơn cả PNG không mất dữ liệu và có nhiễu thấy rõ quanh chữ. Với ảnh chụp màn hình, JPEG đơn giản là sai công cụ.
  3. Thu nhỏ lại làm PNG nặng hơn. Khi thu nhỏ, các điểm ảnh cạnh nhau được trộn lẫn, tạo ra hàng nghìn màu trung gian dọc theo mọi đường viền, mà nén không mất dữ liệu xử lý những màu này rất kém. Cũng ảnh đã thu nhỏ đó, lưu bằng WebP mất dữ liệu lại nhỏ nhất trong tất cả.
  4. AVIF nhỏ nhất ở độ phân giải gốc, nhỏ hơn WebP khoảng một phần ba.

Các con số này chỉ từ một ảnh chụp màn hình. Ảnh nhiều chi tiết hơn hoặc ảnh chụp thật sẽ cho số khác, nhưng thứ hạng giữa các định dạng thường giống như vậy. Với ảnh chụp, so sánh của chính Google cho thấy WebP mất dữ liệu nhỏ hơn JPEG 25-34% ở chất lượng tương đương, còn WebP lossless nhỏ hơn PNG khoảng 26%. AVIF thường còn tiết kiệm hơn nữa, nhất là ở mức chất lượng thấp.

Thu nhỏ trước, nén sau

Phần tiết kiệm lớn nhất gần như không bao giờ đến từ định dạng, mà đến từ việc không gửi những điểm ảnh không ai nhìn thấy. Một ảnh 4000×3000 chụp từ điện thoại hiển thị trong cột rộng 800 pixel chứa số điểm ảnh gấp khoảng 25 lần mức cần thiết (khoảng 6 lần trên màn hình 2×).

Quy tắc thực tế:

  • Tìm kích thước lớn nhất mà ảnh thực sự được hiển thị, nhân 2 cho màn hình mật độ cao, rồi thu nhỏ về đúng kích thước đó. Với cột nội dung blog thông thường, rộng 1600 pixel là quá đủ.
  • Dùng srcset và sizes để điện thoại tải file nhỏ hơn máy tính:
<img
  src="hero-1600.webp"
  srcset="hero-800.webp 800w, hero-1600.webp 1600w"
  sizes="(min-width: 960px) 800px, 100vw"
  width="1600" height="900"
  alt="Tổng quan dashboard">
  • Luôn đặt width và height (hoặc aspect-ratio trong CSS). Trình duyệt sẽ giữ chỗ trước khi ảnh tải xong, tránh bố cục bị nhảy.
  • Thêm loading="lazy" cho ảnh nằm phía dưới màn hình đầu tiên, nhưng không dùng cho ảnh chính ở đầu trang (phần tử LCP). Ảnh đó nên dùng fetchpriority="high".

Mức chất lượng nên dùng

Con số chất lượng không so sánh được giữa các định dạng. "80" của JPEG không giống "80" của AVIF. Điểm khởi đầu tốt:

Định dạng Bắt đầu từ Ghi chú
JPEG 75-85 Trên 90 thì dung lượng tăng nhanh mà mắt gần như không thấy khác
WebP 75-80 Kiểm tra chữ và đường mảnh nếu là ảnh chụp màn hình
AVIF 45-60 AVIF vẫn đẹp ở những mức mà JPEG đã trông rất tệ

Sau đó xem kết quả ở mức zoom 100%, trên loại màn hình người dùng của bạn hay dùng. Hãy để ý khuôn mặt, màu da, bầu trời chuyển màu (dễ bị sọc) và chữ nhỏ. Nếu không thấy khác biệt, thử giảm thêm 5-10 điểm.

Hai thói quen nữa rất có ích:

  • Giữ lại ảnh gốc. Mỗi lần nén mất dữ liệu lại mất thêm một chút chi tiết ("generation loss"). Luôn nén từ bản gốc, đừng nén lại từ một bản đã nén.
  • Xóa metadata. Ảnh chụp từ điện thoại chứa dữ liệu EXIF, có thể gồm cả tọa độ GPS nơi chụp ảnh. Phần lớn công cụ tối ưu đều xóa dữ liệu này, vừa bớt vài KB vừa bảo vệ quyền riêng tư của bạn.

Dùng định dạng mới kèm phương án dự phòng

Mọi trình duyệt hiện tại đều hỗ trợ WebP, nên với phần lớn website chỉ dùng WebP là đủ. Nếu muốn thêm AVIF để tiết kiệm hơn, hãy dùng <picture> để mỗi trình duyệt tự chọn định dạng tốt nhất mà nó hiểu:

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" width="1200" height="800" alt="Ảnh cả nhóm">
</picture>

Các framework như Next.js (next/image) và phần lớn CDN ảnh tự làm việc này dựa trên header Accept mà trình duyệt gửi lên. Nếu bạn đang dùng một trong số đó, hãy kiểm tra AVIF đã được bật trong cấu hình chưa, vì nó thường bị tắt mặc định do mã hóa chậm hơn.

Hướng dẫn chọn nhanh

  • Logo hoặc icon → SVG.
  • Ảnh chụp → thu nhỏ, rồi lưu WebP chất lượng 75-80 (hoặc AVIF 45-60), JPEG chỉ để dự phòng.
  • Ảnh chụp màn hình hoặc sơ đồ → PNG đã tối ưu hoặc WebP lossless; thử WebP/AVIF mất dữ liệu rồi kiểm tra phần chữ.
  • Cần nền trong suốt → PNG, WebP hoặc AVIF, không bao giờ dùng JPEG.
  • Ảnh động → video MP4/WebM hoặc WebP động thay cho GIF.

Với vài ảnh lẻ, bạn không cần dựng cả một quy trình build. Công cụ Nén ảnh của nicetool.dev thu nhỏ và chuyển đổi JPEG, PNG, WebP (và AVIF nếu trình duyệt của bạn mã hóa được) ngay trong trình duyệt. Ảnh không bao giờ bị tải lên máy chủ, metadata được xóa, và bạn có thể so sánh dung lượng trước và sau của từng ảnh trước khi tải về.

Tác giả

Nguyễn Thành Nam

Full-Stack Engineer · Backend & Platform

Kỹ sư full-stack với hơn 9 năm kinh nghiệm xây dựng API và nền tảng lưu lượng lớn bằng Go, NestJS, PHP (Laravel, Phalcon) và Node.js. Chuyên về thiết kế API GraphQL, hệ thống thời gian thực và tối ưu hiệu năng; xây dựng NICETOOL.dev cho cộng đồng lập trình viên.

Tự thử ngay

Bài viết liên quan