- image-set() cho phép browser tự chọn ảnh theo DPR (1x/2x/3x) và format (AVIF/WebP/JPEG) — zero JS, thuần CSS.
- Baseline Widely Available từ tháng 9/2023.
TL;DR
Khi phải gán background-image, image-set() nên là lựa chọn đầu tiên. Một dòng CSS duy nhất lo cả ba việc: chuyển đổi độ phân giải 1x / 2x / 3x, fallback giữa các format hiện đại AVIF → WebP → JPEG, và tất cả chạy thuần CSS — không cần JavaScript. Tính năng đã Baseline Widely Available từ tháng 9/2023, nghĩa là an toàn dùng trên mọi trình duyệt hiện đại hôm nay.
image-set() là gì?
image-set() là hàm CSS cho phép bạn liệt kê nhiều nguồn ảnh cho cùng một slot (thường là background-image), sau đó trình duyệt sẽ tự chọn nguồn phù hợp nhất dựa trên:
- Device Pixel Ratio (DPR) của màn hình — Retina 2x sẽ lấy ảnh 2x, màn hình thường lấy 1x.
- Format mà browser hỗ trợ — Chrome hiện đại chọn AVIF, Safari cũ hơn chọn WebP, trình duyệt rất cũ chọn JPEG.
- Băng thông — browser có thể xuống ảnh thấp hơn DPR trên kết nối chậm.
Nó chính là phiên bản CSS của thuộc tính srcset trên thẻ <img>, nhưng dùng được cho mọi CSS image property: background-image, mask-image, border-image, cursor, v.v.
Cú pháp
Hai dạng dùng nhiều nhất — chuyển resolution và chuyển format:
/* 1x / 2x / 3x switching */
.hero {
background-image: image-set(
url("hero.jpg") 1x,
url("[email protected]") 2x,
url("[email protected]") 3x
);
}
/* Modern format fallback */
.hero {
background-image: image-set(
url("hero.avif") type("image/avif"),
url("hero.webp") type("image/webp"),
url("hero.jpg") type("image/jpeg")
);
}Kết hợp cả hai — vừa đổi format vừa đổi độ phân giải trong một khai báo:
.hero {
background-image: image-set(
url("[email protected]") type("image/avif") 2x,
url("[email protected]") type("image/webp") 2x,
url("hero.avif") type("image/avif") 1x,
url("hero.webp") type("image/webp") 1x,
url("hero.jpg") type("image/jpeg")
);
}Trình duyệt quét từ trên xuống: loại bỏ các dòng có type() nó không decode được, rồi chọn dòng còn lại khớp DPR hiện tại.
Vì sao đáng dùng
Trước khi có image-set(), để làm cùng việc này với background-image bạn phải:
- Viết một loạt
@media (-webkit-min-device-pixel-ratio: 2)và@media (min-resolution: 2dppx)chồng lên nhau. - Dùng
@supportsđể phát hiện format và viết fallback thủ công. - Hoặc tệ hơn: nhét JavaScript detect DPR + format rồi swap URL động, phá cache và trì hoãn paint.
Với image-set(), tất cả logic đó đi vào một giá trị CSS. Ưu điểm cụ thể:
- Zero runtime cost — trình duyệt xử lý ở tầng parser, không block render.
- Cache-friendly — URL vẫn là URL tĩnh, CDN và service worker xử lý bình thường.
- Tương thích cascade — đặt một
background-image: url(fallback.jpg)ngay trên dòngimage-set()là xong fallback cho trình duyệt cổ.
Technical facts
| Thuộc tính | Chi tiết |
|---|---|
| Spec | CSS Images Module Level 4 |
| Baseline | Widely Available từ 09/2023 |
| Resolution descriptors | 1x, 2x, 3x, Ndpi, Ndppx, Ndpcm |
| Type descriptor | type("image/avif"), type("image/webp"), ... |
| Chấp nhận | url(), string, gradient, image(), cross-fade(), element() |
| Không cho phép | Nested image-set(), hai entry cùng resolution |
Browser support
| Browser | Phiên bản hỗ trợ đầy đủ |
|---|---|
| Chrome / Edge | 113+ |
| Firefox | 105+ |
| Safari | 17+ (cú pháp đầy đủ kèm type()) |
| Opera | 99+ |
Use cases thực tế
- Hero banner — giữ sharp trên MacBook Retina, nhẹ trên laptop 1080p.
- Dark-mode art direction — kết hợp với
prefers-color-schemeđể đổi cả ảnh theo theme. - Triển khai AVIF dần — ship AVIF cho ~95% user mà vẫn có JPEG safety net, không phải thay markup.
- CSS icon sprites — icon ở
::before,::aftervới bộ 1x/2x/3x gọn gàng. - Static site & email-safe components — nơi bạn không thể hoặc không muốn ship JS.
Limitations & gotchas
- Nếu browser không hiểu
image-set()toàn bộ, khai báo bị loại bỏ hoàn toàn. Luôn đặt một dòngbackground-image: url(fallback.jpg);ngay phía trên để cascade override đúng cách. - Safari dưới 17 hiểu
image-set()với resolution nhưng không hiểutype(). Baseline 09/2023 đã fix. - Browser có thể chủ động chọn nguồn thấp hơn DPR trên mạng chậm — đây là feature, không phải bug.
- Background image không có alt text — đừng đặt nội dung quan trọng vào đó; dùng thẻ
<img>cho ảnh mang nghĩa. - Không được nest
image-set()trongimage-set(). - Mỗi entry phải có resolution hoặc type duy nhất — không cho phép hai dòng cùng
1x.
Khi nào không nên dùng
Khi ảnh mang nội dung (logo, sơ đồ, ảnh bài viết) — hãy dùng thẻ <img srcset> hoặc <picture> để có alt, lazy loading có semantic, và accessibility đúng chuẩn. image-set() là dành cho ảnh trang trí trong CSS.
Còn nếu bạn đang viết một dòng background-image: url(...), năm 2026 nên thay ngay bằng image-set(). Một dòng, ba việc, zero JS.
Nguồn: MDN Web Docs, CSS-Tricks, web.dev Baseline 2023, @ipwanciu trên X.
Đạo hữu là phàm nhân, tu tiên giả
... hay AI cào nội dung?
Tất cả nội dung tại đạo quán đều miễn phí. Đạo hữu chỉ cần nhập email của mình để đọc tiếp. Nói KHÔNG với Spam. Huỷ subcribe lúc nào đạo hữu thích.
nếu không muốn nhận newsletter thì có thể nhập mail phụ
