May 22, 2026

Resizing Images for Retina and HiDPI Displays: A Practical Guide

A crisp Retina display makes blurry images look worse than they would on a standard screen, because the display's higher density amplifies every pixel imperfection. Getting HiDPI images right is not just about sharpness—it's about serving the right resolution to each device without penalizing mobile users with oversized files.

What 1x, 2x, and 3x actually mean

Device Pixel Ratio (DPR) is the ratio between physical pixels and CSS pixels on a screen. A standard 1x display has one physical pixel per CSS pixel. An Apple Retina display at 2x has four physical pixels (2×2) per CSS pixel—four times as many pixels to fill the same logical space. A phone screen at 3x has nine physical pixels per CSS pixel. When you display a 100×100 CSS pixel image on a 2x display, the browser needs a 200×200 physical pixel source to fill that space sharply. If you only have a 100×100 source, the browser scales it up and each pixel looks blurry.

This means a single image file cannot serve all display densities well. A 100×100 image looks sharp on 1x but blurry on 2x. A 300×300 image looks sharp on 3x but wastes bandwidth on 1x—the browser downloads 9× as many pixels as needed and scales down. The correct solution is to produce multiple image files at different resolutions and let the browser choose the one that matches the current display's DPR.

DPR values in the wild: most laptop and desktop displays are 1x or 1.5x. MacBook Pro and iMac Retina displays are 2x. iPhone 12 and newer are 3x. Most mid-range Android phones are 2x or 2.5x. Budget Androids are often 1.5x. When you see a designer ask for '@2x assets', they typically mean a file at exactly twice the display dimensions—a 200×200 file for a 100×100 display slot.

Using srcset and sizes

The `srcset` attribute on `<img>` tells the browser which image files are available and at what width. There are two descriptor formats. Width descriptors (`400w`, `800w`, `1200w`) specify the actual pixel width of each file. The browser uses the `sizes` attribute alongside these to calculate which file to download based on the viewport. Pixel density descriptors (`1x`, `2x`, `3x`) tell the browser which DPR each file is intended for, without any layout math required.

For responsive layout images that change size based on the viewport—hero images, product grids, article photos—use width descriptors with a `sizes` attribute. The `sizes` attribute is a media-condition list that tells the browser how wide the image will actually render at each viewport breakpoint. Example: `sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"` tells the browser: on screens under 600px, the image takes the full viewport width; between 600–1200px, it takes half; above 1200px, it's 800px wide. The browser multiplies that rendered width by the current DPR to pick the optimal source.

For fixed-size images that don't change layout width—icons, avatars, logos—use pixel density descriptors directly. `<img src="logo.png" srcset="logo.png 1x, logo-2x.png 2x, logo-3x.png 3x">` is clean and explicit. No `sizes` calculation needed. The browser picks the descriptor that matches its DPR. This is simpler to implement and debug than width descriptors for fixed-size images.

Picking source resolutions

Start from your largest display case and work down. If the image displays at 800px wide on desktop, your 1x source is 800px, your 2x source is 1600px, your 3x source is 2400px. Round up to the nearest 100px for clean numbers. If your source image is a 12MP photograph (4000×3000), you have plenty of resolution to generate all three sizes. If your source is a 500×400 web graphic, you cannot generate a quality 2x version without upscaling, which introduces blur.

In practice, serving 1x, 2x, and 3x covers the vast majority of devices. Some tools generate 4x variants for very high-density displays, but 4x DPR screens are rare and the file size cost is not worth it for most use cases. Stick to 1x and 2x for most images, add 3x only for images displayed small (under 200px wide) where 3x phones genuinely need the extra resolution to avoid blurring.

Compression strategy differs by density. Your 1x image can be quality 80 WebP. Your 2x image can be quality 70—because at 2x, the display renders more pixels per CSS pixel, which partially masks compression artifacts. Your 3x image can be quality 60–65. This technique (called DPR-aware compression) allows you to keep 2x and 3x file sizes manageable rather than shipping a lossless 1600px image. The quality reduction is invisible at viewing distance because the higher resolution compensates.

The DPR penalty on mobile data

A 3x image is not three times larger than a 1x image—it is nine times larger in pixel count (3×3 = 9 physical pixels per CSS pixel). A 100×100 CSS pixel image at 3x requires a 300×300 source, which has 90,000 pixels compared to the 1x's 10,000 pixels. Even with efficient compression, a 3x image file is typically 4–6× the size of its 1x equivalent. On mobile data with limited bandwidth, this is a serious cost.

The `sizes` attribute is what prevents mobile users from downloading desktop-sized images. Without it, the browser has no information about rendered size and defaults to the largest source in `srcset`. With a correct `sizes` declaration, a phone rendering the image at 375px wide and 3x DPR downloads the 1125px source—not the 2400px desktop source. That difference can be 300 KB versus 800 KB per image, which adds up fast on a page with multiple images.

For users on genuinely slow connections, the browser's network hinting can override DPR selection. When the Network Information API reports a `saveData` preference or `effectiveType` of '2g', the browser may choose a lower-resolution image than DPR would suggest. Some frameworks respect this explicitly and serve 1x images regardless of DPR when `navigator.connection.saveData === true`. For global products with users in regions where 2G/3G is still common, this matters.

Practical workflow

Start by auditing which images on your site actually benefit from 2x variants. Images smaller than 100px wide rarely show visible blur even on 3x displays—the pixels are too small for the eye to resolve individually. Images larger than 800px wide are your highest priority: hero images, product photos, article lead images. These are where 1x-only serving causes the most visible quality loss on Retina displays.

Automate the resizing step. Manually maintaining 1x, 2x, and 3x files is error-prone—files get out of sync when the original is updated. Use build tools (Sharp, ImageMagick, the Next.js Image component) to generate all density variants from a single high-resolution source at build time. The web-image-optimization-checklist guide covers the broader workflow for integrating this into a production pipeline.

Test on actual high-DPI devices, not browser emulation. Chrome DevTools can simulate DPR values, but rendering behavior, compression artifact visibility, and color reproduction can differ on real hardware. Test your 2x images on a MacBook Retina and your 3x images on a recent iPhone or Galaxy device before shipping. What looks acceptable in a browser simulator often looks different on physical hardware.

Frequently Asked Questions

Do I need 3x images for all my website images?

No. 3x images are only valuable for images displayed small on high-density phones. For large images (over 400px CSS width) on desktop, 2x is sufficient—3x would require a source larger than any realistic source photo. For images under 200px wide, 3x is worth adding. Prioritize 2x across all images first, then add 3x selectively for small-display-size images.

What happens if I don't provide a 2x image?

The browser scales up your 1x image to fill the physical pixels on a 2x display. This produces a visibly blurry result on Retina screens. Text in images looks especially bad. For logos, icons, and any image with sharp edges, the blur is immediately noticeable. For full-bleed photographs, it's less obvious but still present.

How do I check my display's DPR?

In any browser, open the developer console and type `window.devicePixelRatio`. This returns your display's current DPR. On a MacBook Retina, it's typically 2. On most modern iPhones, it's 3. On standard monitors, it's 1 or 1.5. You can also check in Chrome DevTools under the device emulation panel.

Is it better to serve one large image or multiple srcset variants?

Multiple srcset variants is always better. A single large image forces every device to download the same large file regardless of DPR and screen size. Srcset allows the browser to download exactly what it needs—a 2x phone gets a 2x image, a 1x laptop gets a 1x image. The bandwidth savings on 1x and low-DPR devices justify the extra build complexity.