Reviewed November 11, 2026
Your Product Images Are 56 Times Too Big: Sizing Rules That Move LCP
Images are 50 to 80 percent of a Shopify store's page weight, and the most common mistake is uploading an image far larger than the screen that displays it. A 4000 by 4000 pixel image displayed at 800 by 800 wastes 96 percent of its pixels, and a 3000 by 3000 image shown at 400 by 400 sends 56 times more data than necessary. Shopify does not compress your original uploads: a 5 megabyte image is stored as-is and delivered as a 1 to 2 megabyte file. The fix is to upload at the right size, 2048 by 2048 for product images with a target of 100 to 200 kilobytes, and to serve responsive widths with srcset, so a phone gets a 400 pixel image and a desktop gets a 1200 pixel one. The hero image is almost always the LCP element, so it must never be lazy-loaded.
The pixels nobody sees
Images typically account for 50 to 80 percent of total page weight on Shopify stores, and a single uncompressed product photo can be 3 to 8 megabytes when it should be 100 to 300 kilobytes. The waste is not in the image you can see. It is in the pixels you cannot. Uploading oversized images is one of the most common mistakes: a 4000 by 4000 pixel image that displays at 800 by 800 wastes 96 percent of its pixels, and serving a 3000 by 3000 product image to a mobile visitor whose screen displays it at 400 by 400 sends 56 times more data than necessary. Every pixel beyond what is needed on screen is wasted bandwidth, and it is especially costly for mobile visitors, who are often on slower connections and smaller screens. The hero image is usually the LCP element, so the waste lands directly on the metric Google uses to judge the page.
Shopify does not save you from yourself
The misunderstanding is that Shopify handles this. It does not. Shopify does not compress your original uploads: if you upload a 5 megabyte image, that 5 megabyte file is stored as-is, and it is delivered as a 1 to 2 megabyte file after resizing. What Shopify does provide is delivery infrastructure: the CDN automatically converts to WebP when you use the image_url Liquid filter, WebP is 25 to 35 percent smaller than JPEG at equivalent quality and supported by more than 97 percent of browsers, and the CDN can resize on the fly with a width parameter. But the compression of the source file is your job, before upload. The practical targets are simple: product images at 2048 by 2048 pixels, square, at 100 to 200 kilobytes; hero and banner images at 1600 to 2000 pixels wide, at 150 to 300 kilobytes, and under 180 kilobytes if you can manage it without losing clarity; thumbnails at 800 by 800, at 50 to 100 kilobytes. Many slow stores use hero images between 300 and 400 kilobytes, and sometimes over 900, and that alone can push LCP past the 2.5 second threshold.
Responsive widths, and the two rules that matter
Responsive images serve different sizes for different screens: a phone gets a 400 pixel image, a desktop gets 1200. The image_url filter makes this a one-line change in Liquid, with a srcset of 400, 800, and 1200 widths, and a sizes attribute that tells the browser which one to pick. Mobile users end up downloading about four times less data. Most modern Shopify themes include srcset support, but check that yours generates at least three breakpoints, 375, 750, and 1500, and that the sizes attribute matches the layout. Then there are two rules that matter more than the sizing. First, never lazy-load the hero image or above-the-fold product images: lazy loading delays loading until the user scrolls near, which dramatically reduces initial page weight on a collection page, but the hero is the LCP element, and delaying it delays the metric. Second, specify width and height on every image, which reserves space and prevents layout shift even before the image loads. Shopify's image_tag helper does this by default. A collection page with 40 products only loads the first 4 to 8 images upfront when lazy loading is set up right, and the hero loads eagerly with fetchpriority high. That is the whole system: right size, right width per device, hero eager, everything else lazy.
Related reading
For the background behind “Your Product Images Are 56 Times Too Big: Sizing Rules That Move LCP”, these earlier guides help: fetchpriority High on the Hero Image: The One Attribute That Moves LCP, AVIF vs WebP for Hero Images: The Cheapest LCP Win on Shopify, and Lazy Loading Below the Fold: Where It Helps LCP and Where It Hurts.
Frequently asked questions
What size should Shopify product images be?
2048 by 2048 pixels, square, with a target file size of 100 to 200 kilobytes. That is sharp enough for zoom and retina displays, and small enough for mobile LCP. The minimum for zoom is 1024 by 1024. The maximum Shopify accepts is 4472 by 4472 pixels and 20 megabytes per image, but uploading at the maximum is the mistake, not the goal.
Does Shopify compress my images automatically?
No. Shopify does not compress your original uploads. If you upload a 5 megabyte image, that 5 megabyte file is stored as-is, and it is delivered as a 1 to 2 megabyte file after resizing. The CDN automatically converts to WebP when you use the image_url Liquid filter, and it can resize on the fly with a width parameter, but it does not compress the source file for you. Compress before you upload.
How does srcset work on Shopify?
The image_url Liquid filter takes a width parameter, and the theme builds a srcset from it: a 400 pixel version for phones, 800 for tablets, 1200 for desktops, and the 2048 master for large screens. The browser picks the smallest version that fits the display, so a mobile visitor downloads about four times less data than a desktop visitor. Most modern Shopify themes include srcset support, but check that yours generates at least three breakpoints, 375, 750, and 1500.
Should I lazy-load my hero image?
No. Never lazy-load your hero image or above-the-fold product images. The hero is almost always the LCP element, and lazy loading tells the browser to delay the most important image on the page. Lazy load everything below the fold, and load the hero eagerly with fetchpriority high and a preload in the head, which shaves 200 to 600 milliseconds off mobile LCP.