返回资讯中心
外部精选
软件工程
#社区热议

JPEG XL vs. AVIF for web use-cases

JPEG XL has now landed in all major browsers, so I figured I'd take a closer look at what it's good/bad at compared to other formats.

Hacker Newsfarlight2026/10/16 · 11 天前30 分钟阅读

以下正文同步自 Hacker News,版权归原站所有,已转换为易读排版。

JPEG XL has now landed in all major browsers, so I figured I'd take a closer look at what it's good/bad at compared to other formats.

I'll go into full detail, with examples and benchmarks, but for those of you who don't have the time, here are the headlines:

For lossy photos on the web, AVIF almost always produces smaller files than JPEG XL. At default effort settings, the best JPEG XL version is typically 15–25% larger than the equivalent AVIF. At maximum effort settings, the gap narrows a little, to typically 6–20%. There are outliers, where JPEG XL is close to, or even beats AVIF, so if you want the absolute best result for a particular image, it's worth trying both. See the F1 image for a typical example, and the weasel for an outlier.

The JPEG XL encoder matters a lot. jixel, a newer JPEG XL encoder, usually produces smaller files than libjxl, except when the image has detailed transparency. The people image is one example.

For screenshots and illustrations, AVIF is much better than JPEG XL. The equivalent JPEG XL is 30–90% larger at default effort settings, and 20–70% larger at maximum effort settings. Lossy AVIF handles these well - you don't need to use lossless formats unless you really need bit-exact results. See the screenshot and illustration examples.

For images with transparency, AVIF is much better than JPEG XL. The libjxl version is 31–44% larger at default effort settings, and 61–70% larger at maximum effort settings. jixel always encodes transparency losslessly, which makes its files 2–3x the size of AVIF's. See the data.

AVIF is generally faster to encode, and uses less memory, when you factor in file size. jixel is faster than AVIF and uses less memory, but its files are typically significantly larger, so AVIF is better on balance. See the F1 image for one example.

AVIF is faster to decode. JPEG XL typically takes 2–3x as long to decode at medium quality, but the gap narrows at very high qualities, where Chrome can sometimes decode JPEG XL faster. The people image is one example.

Higher effort settings are worth it for AVIF and jixel, but not libjxl. libjxl's higher efforts are much slower, use a lot more memory, and barely improve the result. Sometimes they produce larger files than the default effort. The screenshot is an example of this.

AVIF's 4:2:0 mode (half colour resolution) shouldn't be your default. It rarely reduces file size, and it makes higher qualities harder to reach. Although, it is quicker to encode and decode. Stick with 4:4:4 if you don't have time to check both. The F1 image is one example, and the screenshot is an exception.

Quality settings are reliable for all the encoders. With a single quality setting, the resulting quality varies a bit between images, but all the encoders vary in the same direction, and in ways that seem reasonable. See the data.

Progressive JPEG XL is basically free at high effort. jixel recently added support for early progressive previews, and at its slowest setting they cost little or nothing, but at its default setting the files are 12% bigger. Firefox and Chrome support progressive JPEG XL. Safari still renders the final image, but doesn't show progressive previews. However, is this type of progressive rendering a good user experience? See the examples and data.

AVIF supports progressive rendering! It's Chrome-only for now, but it's in progress for Firefox. It's more complex than progressive JPEG XL, but it gives you more control over what the preview looks like, the files are usually smaller, and they're much faster to decode. See for yourself.

For HDR, JPEG XL lacks gain maps, which is a significant limitation compared to AVIF. The JPEG XL format supports gain maps, but they aren't supported by browser decoders, and the encoding story is messy/experimental. When comparing non-gain mapped HDR content, the two quality metrics I used disagree a lot, but they agree that JPEG XL produces smaller files compared to AVIF. See the examples.

JPEG XL can make existing JPEGs 9–20% smaller, without further loss. It's also as fast or faster to decode, except for small images. See the data.

For lossless, JPEG XL is the clear winner. Lossless WebP is 9–17% larger for photos, and lossless AVIF is 30–120% larger. But lossless images are almost never what you want on the web. If you do use them on the web (like I do on this page), watch out for jixel's higher efforts - it often produces files that are too slow to decode. See the data.

Animated image formats continue to be a dumb idea. Please don't use them. Learn more, if you must.

For web use-cases, I'd currently default to AVIF 4:4:4, with the highest effort level I can be bothered with. If I felt AVIF was producing an unusually large file, I'd take a look at JPEG XL via jixel, and see if it did better.

Both AVIF and JPEG XL (via jixel) have seen massive improvements recently, so it's possible that this recommendation could change in future. There's been a lot of misinformation around this stuff, and your AI will happily deliver that misinformation to you. Instead, test things with your own images.

AVIF folks suggest that JPEG XL is technically limited compared to AVIF. That might be true, but in this article I'm focusing on results with today's implementations.

I 'created' a benchmarking script, that encodes images using various codecs at various settings, and records various details.

I'm using the latest released versions of the image codecs, which at time of writing is:

I chose a selection of images, and encoded most of them to a width of 1598 pixels - which is 2x the maximum width images appear on this blog. This means they look sharp on high density displays, which most users have. As a result, if you're viewing this on a small or low density screen, you're not getting the full experience.

I ran these benchmarks on my 2024 MacBook Pro (M4 Pro).

'); background-size: 20px 20px; } .codec-compare-layer { position: absolute; inset: 0; } .codec-compare-layer img, .codec-compare-layer canvas { position: absolute; top: 0; left: 50%; width: 100%; height: 100%; transform: translateX(-50%); } .codec-compare-layer img { /* Holding the image shows lossless, so don't let a long-press start a drag / -webkit-user-drag: none; } .codec-compare-button { position: absolute; font: inherit; font-size: 0.9rem; padding: 0.5em 0.9em; border: none; border-radius: 100px; background: rgba(0, 0, 0, 0.7); color: #fff; cursor: pointer; touch-action: manipulation; } .codec-compare-hold { right: 10px; bottom: 10px; } .codec-compare-fullscreen { right: 10px; top: 10px; display: grid; padding: 0.45em; } .codec-compare-fullscreen svg { width: 1.3em; height: 1.3em; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } .codec-compare-hold[aria-pressed=true] { background: #ffe454; color: #000; } .codec-compare:fullscreen { display: flex; flex-direction: column; background: #fff; } / Avoids notches etc when the preview reaches the edges of the screen / .codec-compare:fullscreen .codec-compare-fullscreen { top: max(10px, env(safe-area-inset-top)); right: max(10px, env(safe-area-inset-right)); } .codec-compare:fullscreen .codec-compare-preview { flex: 1; min-height: 0; } .codec-compare:fullscreen .codec-compare-scroller { position: absolute; inset: 0; overflow: auto; display: flex; } / Shown at its 2x size, or smaller if it doesn't fit the width / .codec-compare:fullscreen .codec-compare-frame { flex: none; / Centres, but unlike align/justify-content, it doesn't clip when scrolled / margin: auto; width: var(--max-width); max-width: 100%; } .codec-compare:fullscreen .codec-compare-layer img, .codec-compare:fullscreen .codec-compare-layer canvas { / Overrides DecodedImg's inline width, so it shrinks with the frame / width: 100% !important; } .codec-compare-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 2rem; padding: 1rem; font-size: 0.9rem; line-height: 1.3; } / Give the formats more room. The slider has few steps, so it can spare it. */ .codec-compare-controls-many { grid-template-columns: 1fr 3fr; } @media (max-width: 600px) { .codec-compare-controls { grid-template-columns: 1fr; } } .codec-compare-heading { display: block; font-weight: bold; padding: 0; margin-bottom: 0.6em; } .codec-compare-description { font-weight: normal; } .codec-compare-slider { display: block; width: 100%; margin: 0; height: 22px; background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer; } .codec-compare-slider::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: #ffe454; } .codec-compare-slider::-moz-range-track { height: 6px; border-radius: 3px; background: #ffe454; } .codec-compare-slider::-webkit-slider-thumb { -webkit-appearance: none; margin-top: calc((6px - 22px) / 2);

width: 22px; height: 22px; border-radius: 50%; border: none; background: #000;

} .codec-compare-slider::-moz-range-thumb {

width: 22px; height: 22px; border-radius: 50%; border: none; background: #000;

} .codec-compare-ticks { position: relative; height: 1.3em; margin-top: 0.3em; } .codec-compare-tick { position: absolute; /* Line up with the centre of the thumb at each step */ left: calc(22px / 2 + (100% - 22px) * var(--pos)); transform: translateX(-50%); } .codec-compare-codecs { border: none; margin: 0; padding: 0; min-width: 0; } .codec-compare-codec-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(7em, 1fr)); gap: 0.5rem; } .codec-compare-codec { display: grid; cursor: pointer; } .codec-compare-codec input { position: absolute; opacity: 0; pointer-events: none; } .codec-compare-codec-inner { display: grid; gap: 0.3em; padding: 0.6em 0.7em; border: 2px solid #ffe454; } .codec-compare-codec input:checked + .codec-compare-codec-inner { background: #ffe454; } .codec-compare-codec input:focus-visible + .codec-compare-codec-inner { outline: 2px solid #000; outline-offset: 2px; } .codec-compare-codec-name { font-weight: bold; } .codec-compare-bar { display: block; height: 6px; background: rgba(0, 0, 0, 0.08); } .codec-compare-bar span { display: block; height: 100%; transition: width 200ms ease-out; } .codec-compare-codec-score { font-size: 0.8rem; } Lossy - F1 image

Hold for lossless

SSIMULACRA2 target: 70 (high)5060708090

FormatAVIF41.4 kBSSIMULACRA2: 70.2JPEG XL (libjxl)58.4 kB (+41%)SSIMULACRA2: 70.0JPEG XL (jixel)46.6 kB (+12%)SSIMULACRA2: 70.0

When I first wrote about AVIF, I used an F1 car as the first image, so I figured I'd do that again!

I encoded the image at various codec qualities, and chose versions that were closest to particular SSIMULACRA2 scores - a perceptual image quality metric by the folks behind JPEG XL. 50 is considered medium quality, 70 high, 80 very high, and 90 visually lossless. Although, I'm not sure if these ratings take high density displays into account.

Throughout the article, the visual comparisons, like above, use each encoder's maximum effort, except in cases where maximum effort results in a larger file (yes, that happens).

For archival, I'd tend towards near-lossless qualities, but if I'm just displaying an illustrative image on my blog, performance is more important to me. I'm personally happy with the 70 result above. If you zoom in, you can see the quality loss, but if I was really concerned about the zoom-in case, I'd use something like the VisualViewport API to load in a higher resolution image when that happens, rather than make the download bigger for everyone.

At lower qualities you can see the difference in strategy between the codecs. The detail loss is around the same, but AVIF tends to smooth things out compared to the original, whereas JPEG XL seems to introduce rougher patterns.

Also, I feel that, at medium quality (50), the AVIF and libjxl look better than the jixel version. The jixel ver

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →