Three Concepts, One Sentence#

"This image is too big." That sentence can mean three completely different problems:

  1. File size is too large — downloads slowly ("this PNG is 5MB")
  2. Pixel dimensions are too large — overflows the container ("this image is 6000px wide")
  3. DPI is being misinterpreted — "this image is only 72 DPI so the quality is bad"

Most people blur these together. Separating them puts you ahead of the crowd.

Resolution, dimensions, and file size relationship
Resolution, dimensions, and file size relationship

Pixel Dimensions#

Pixel dimensions are an intrinsic property of the image — how many pixels wide and tall it is:

bash
1exiftool -ImageWidth -ImageHeight photo.jpg
2# ImageWidth: 4032
3# ImageHeight: 3024
4# This is a 4032 x 3024 pixel image, roughly 12 megapixels

Pixel dimensions determine:

  • The maximum display size without scaling
  • How much total information is available to compress
  • The physical size when printed (combined with DPI)

Pixel Dimensions and Screen Display#

text
1A 1200px-wide image on a:
2 - 390px phone screen → scaled down to 32.5% of original
3 - 1440px desktop monitor → displayed at near-native size
4 - 800px card component → scaled down to 66% of original

When an image's pixel width exceeds 3x its rendered width, you are shipping pixels the user cannot see. The extra resolution contributes nothing visually but adds directly to download time, data consumption, and decode cost.

DPI / PPI: A Print Concept, Not a Screen Concept#

DPI (Dots Per Inch) and PPI (Pixels Per Inch) matter for print. On the web, they matter almost not at all.

A 1200 x 800px image at 72 PPI and the same 1200 x 800px image at 300 PPI look identical in a browser. The device ignores the DPI metadata and renders the available pixels across whatever CSS dimensions the layout specifies.

bash
1# This value affects printing, not web display
2exiftool -XResolution -YResolution -ResolutionUnit photo.jpg
The one place screen pixel density matters is the device's own DPR (device pixel ratio) — how many physical screen pixels map to one CSS pixel. But that is a property of the hardware, not of any image file's metadata. CSS's resolution media query queries the device, not the image.

The misconception persists because design tools label export presets as "72 DPI" (for screen) and "300 DPI" (for print). Those labels set the DPI metadata field in the exported file. They do not affect how the image looks in a browser. A 1200px image at 72 DPI and a 1200px image at 300 DPI are pixel-identical if exported from the same source.

File Size#

File size is the byte count after compression and encoding:

bash
1ls -lh photo.jpg
2# -rw-r--r-- 1 user staff 2.3M photo.jpg

Five factors determine file size:

  1. Pixel dimensions — more pixels mean more data to encode
  2. Compression algorithm and quality setting — same image: JPEG Q60 might be 200KB, PNG lossless might be 3MB
  3. Image content complexity — at the same resolution, a solid color compresses far smaller than random noise
  4. Color depth and channel count — RGBA carries 33% more data than RGB before compression
  5. Metadata payload — embedded EXIF, ICC profiles, and thumbnails add bytes on top

Mapping "Too Big" to the Real Problem#

SymptomRoot CauseFix
Page loads slowlyFile size too largeIncrease compression, switch to modern format
Image overflows layoutPixel dimensions exceed containerResize source or use srcset
Image looks blurryPixel dimensions too low, or quality too aggressiveProvide more resolution or raise quality
Print looks badNot enough pixels for the target DPIProvide more pixels (300 PPI x print inches)

The Mathematical Relationship#

The three concepts connect through "bytes per pixel" — a simple ratio that tells you whether an image is over-compressed, under-compressed, or roughly right:

js
1function analyzeImage(metadata) {
2 const totalPixels = metadata.width * metadata.height;
3 const bytesPerPixel = metadata.fileSize / totalPixels;
4 const megapixels = (totalPixels / 1_000_000).toFixed(1);
5 
6 return {
7 megapixels: `${megapixels}MP`,
8 fileSizeKB: (metadata.fileSize / 1024).toFixed(1),
9 bytesPerPixel: bytesPerPixel.toFixed(2),
10 assessment: bytesPerPixel > 1.5 ? 'likely under-compressed' :
11 bytesPerPixel < 0.2 ? 'likely over-compressed' : 'reasonable compression',
12 };
13}
14 
15const sharp = require('sharp');
16async function inspect(path) {
17 const meta = await sharp(path).metadata();
18 const stats = await fs.stat(path);
19 return analyzeImage({
20 width: meta.width,
21 height: meta.height,
22 fileSize: stats.size,
23 });
24}
Bytes per pixel comparison across formats
Bytes per pixel comparison across formats

Healthy bytes-per-pixel ranges:

  • JPEG photo: 0.3–1.0 bpp
  • WebP photo: 0.15–0.6 bpp
  • AVIF photo: 0.08–0.3 bpp
  • PNG screenshot/icon: 0.5–3.0 bpp (entirely content-dependent)
These are reference ranges, not hard thresholds. A photo of a blue sky will land at the low end; a photo of a dense forest canopy at the high end. Content complexity drives the same format to different byte counts at the same pixel dimensions — a topic explored in depth in the companion article on same dimensions, different file sizes.

Practical Numbers for Common Contexts#

Site hero image: Displayed at roughly 1280 x 720px on a 1440px desktop. A 1920 x 1080px source covers 2x Retina with margin. Output as AVIF Q50, expect 40–80KB.
Product thumbnail: Displayed at 300 x 300px. A 600 x 600px source covers 2x. Output as AVIF Q45 or WebP Q75, expect 8–15KB.
Blog body illustration: Displayed at roughly 700px wide in the content column. A 1400px-wide source covers 2x. Output as AVIF Q50, expect 25–60KB.
Open Graph share image: Fixed at 1200 x 630px by convention. Output as JPEG Q85, expect 80–150KB. No responsive variants needed since social platforms use the single og:image URL.

The Two Levers#

Pixel dimensions control how much data exists before compression. Compression controls how efficiently that data gets stored. These are the only two levers you have, and they address different problems:

  • If an image is 4000px wide but renders at 800px, compression alone won't fix it. You are shipping 25x more pixel data than necessary, and compression can only reduce the byte cost of each pixel — it can't eliminate the extra pixels.
  • If an image is correctly sized at 1600px but still 500KB, better compression (format choice, quality tuning) is what you need.

The skill is knowing which lever to pull. Most "my images are too big" problems are actually both: the image is too many pixels wide, and it's in a format that stores those pixels inefficiently.