HN Debrief

Why tiny JPEGs look different in Chrome

  • Web
  • Graphics
  • Browsers
  • Performance
  • Developer Tools

The post digs into a small but very visible rendering quirk: a JPEG shrunk to icon size looked different in Chrome than in Firefox. The author tied it to Chrome using partial JPEG decode for aggressive downscaling, which can effectively throw away higher-frequency detail early and change the final look. People filled in the missing browser internals. Firefox is not doing a naive full decode and then scaling either. It uses downscale-during-decode, while Chrome's JPEG path leans on the 8x8 DCT structure more directly for speed. That made the comments land on a broader point than the original bug hunt. Browser image pipelines are full of performance shortcuts, and those shortcuts show up most on tiny UI assets, line art, repeated patterns, and high-contrast edges, not on normal photos where the optimization is usually invisible. The practical consensus was blunt: JPEG is the wrong format for icons, browsers also differ in their resampling choices, and even lossless formats can still look bad if you hand the browser a huge bitmap and ask it to crush it down. SVG came up as the cleanest fix for icons because it survives DPI and zoom changes better, though inline SVG can create its own DOM style and ID collision problems if you do not isolate it.

If image quality matters in UI, stop relying on browser defaults to rescue oversized assets. Ship vector icons where possible, provide raster images near their display size, and test cross-browser rendering at real zoom and DPI settings before rollout.

Discussion mood

Interested and mostly positive. People liked the reverse engineering, but the dominant reaction was that the browser behavior is understandable and the real mistake was using JPEG or oversized bitmaps for tiny UI graphics in the first place.

Key insights

  1. 01

    Firefox also downsizes during decode

    Firefox is not taking the expensive 'decode full image then shrink it' path. It already has a downscale-during-decode pipeline, and Mozilla is also adding lower-scale JPEG decompression work, so the difference here is not 'optimized Chrome' versus 'unoptimized Firefox'. It is two different optimization strategies with different quality tradeoffs.

    Do not assume one browser is doing the obvious reference implementation. If rendering differences matter to your product, test the actual browser pipelines you ship against rather than reasoning from first principles.

      Attribution:
    • the8472 #1
    • muizelaar #1
  2. 02

    Resampling choice may matter more

    The visible gap may be driven at least as much by the scaler as by partial JPEG decode. People pointed out that Chrome looks blurrier and Firefox sharper with more ringing, which matches familiar tradeoffs between faster and sharper filters. The side discussion on PSNR, LPIPS, and FLIP reinforced the same point. 'Better' image quality depends on the artifact people notice first, and engineering metrics do not settle that for UI assets.

    When you compare browser output, separate decode-path effects from scaling-filter effects. If a pixel-perfect result matters, precompute thumbnails with your own chosen filter instead of accepting whatever the browser or GPU picks.

      Attribution:
    • debazel #1
    • aidenn0 #1
    • ryandamm #1
    • m-schuetz #1
    • Theodores #1
  3. 03

    Partial IDCT can expose broken JPEG edges

    Downscaling during JPEG decode can surface encoder sloppiness that full-size decode hides. Some JPEGs leave garbage or zeros in the unused rows or columns of the final MCU, and full decode simply crops that away. Partial IDCT scaling blends those bad edge samples back into visible pixels, which explains why only some files show ugly artifacts.

    If a browser bug seems file-specific, inspect the source JPEG before blaming the renderer. Re-encoding or cropping a few edge pixels can fix production assets without waiting on a browser change.

      Attribution:
    • adzm #1
  4. 04

    SVG fixes scaling but adds isolation work

    Switching icons to SVG solved the quality problem for one product across dark mode, zoom levels, and mixed DPI displays. The catch was operational, not visual. Inline SVGs exported from tools like Adobe Illustrator reused class names and element IDs, which caused icons to style each other unless each one lived in its own Shadow DOM or had its identifiers rewritten.

    Moving to SVG is not just an asset-format change. Budget time for a sanitizing or namespacing step in your icon pipeline, especially if designers export raw SVGs into a large app.

  5. 05

    Browser scaling is not a stable contract

    People stressed that browser downscaling is a performance feature, not a quality guarantee. The algorithm can differ by browser and even by GPU path, and CSS knobs like `image-rendering` only help in some cases because filters that look good on photos often smear line art. That makes browser resizing acceptable for ordinary web content, but unreliable for UI elements where tiny differences are obvious.

    Treat browser image scaling as approximate. For logos, icons, and other sharp assets, ship the right size or use vector art instead of hoping CSS and the browser rasterizer will converge on the same answer everywhere.

      Attribution:
    • kccqzy #1
    • gwittel #1
    • bawolff #1 #2

Against the grain

  1. 01

    PNG is a separate issue

    The claims that Chrome was doing the same trick to PNGs did not hold up. PNG does not support the same kind of partial block decode as JPEG, aside from rare Adam7 interlacing cases, so similar-looking quality problems with PNG are more likely ordinary scaling-filter differences than a decode shortcut.

    Do not generalize a JPEG-specific explanation to every image format. When debugging browser rendering, separate decode behavior from resize behavior before you pick a fix.

      Attribution:
    • polpo #1
    • bawolff #1
    • binaryturtle #1
  2. 02

    ICO may still be useful

    For tiny fixed-size assets around favicon scale, ICO was suggested as an ugly but practical container because it can bundle multiple raster sizes. That sidesteps some browser downscaling problems by letting the browser pick a closer native size instead of crushing one oversized bitmap.

    If you are stuck with raster-only assets at a few known tiny sizes, a multi-resolution container can still be a valid workaround. It is clunky, but better than shipping one giant source and trusting resampling.

      Attribution:
    • altairprime #1

In plain english

Adam7 ↩
An interlacing method for PNG that stores image data in multiple passes so a rough preview can appear before full decoding.
DCT ↩
Discrete Cosine Transform, the JPEG compression technique that represents image data as low- and high-frequency coefficients in 8x8 blocks.
DPI ↩
Dots per inch, a mouse sensitivity setting that affects how far the cursor moves for a given physical movement.
favicon ↩
The small icon shown in a browser tab or bookmark for a website.
FLIP ↩
A perceptual image-difference metric used to compare rendered images in a way meant to align with what people notice visually.
ICO ↩
A Windows icon file format that can store multiple icon sizes and color depths in one file.
IDCT ↩
Inverse Discrete Cosine Transform, a core computation used in many image and video compression formats such as JPEG and MPEG.
image-rendering ↩
A CSS property that lets developers hint how the browser should scale images, such as smoothing or preserving hard pixel edges.
JPEG ↩
A common compressed image format mainly used for photos, which usually does not preserve editing layers or advanced project state.
LPIPS ↩
Learned Perceptual Image Patch Similarity, a machine-learned metric intended to better match human judgments of image similarity.
MCU ↩
Marvel Cinematic Universe, the long-running shared universe of Marvel superhero films and shows.
PNG ↩
A common image format that supports lossless compression and transparency.
PSNR ↩
Peak Signal-to-Noise Ratio, a numeric measure of how different a processed image is from a reference image.
Shadow DOM ↩
A browser feature that gives a component its own isolated DOM subtree so its styles and IDs do not clash with the rest of the page.
SVG ↩
Scalable Vector Graphics, a text-based image format for drawings and interface assets.

Reference links

Browser implementation references

Image quality and rendering examples

Format support and specs

  • Wikipedia: Favicon
    Referenced to explain the messy modern favicon size landscape and inconsistent browser selection behavior.
  • Can I use: AVIF
    Referenced to argue AVIF support is now broad enough to consider over JPEG.

Background references