Shopify Store Still Slow After Optimizing Images? Here Is Why

Shopify speed · Field notes

You compressed every image and the store is still slow. Here is what is actually holding it back.

Compression fixes how many bytes travel down the wire. It does nothing about how much work the phone does when those bytes arrive. On mobile the second problem is usually the bigger one, and it is the reason your score did not move.

By Mohammad UsamaUpdated September 20267 min read
Start here

Bytes are not the same as pixels

Take a product photo that is 2560 pixels wide. Compress it hard and you might get it to 90KB, which looks like a win in every tool that reports file size.

Now think about what the phone does with it. To draw that image the browser has to decode it back out to raw pixels in memory. 2560 by 1441 is roughly 3.7 million pixels, and each one needs four bytes for red, green, blue and alpha. That is about 15MB of memory, produced by roughly 60 to 90 milliseconds of work on the main thread of a mid range phone.

The 90KB file did not get cheaper to decode. It got cheaper to download.

And the slot that image sits in on a phone is maybe 350 pixels wide. You shipped 52 times more pixels than the screen can show, and the phone paid for every one of them.

A real measurement

What this looks like on an actual store

We profiled a store recently where every image had already been compressed and converted to WebP. On a 407 pixel wide viewport the page was still handing the phone 41 megapixels of image data. Roughly 165MB of decoded bitmap.

A phone cannot hold that. So it decodes an image, draws it, then evicts it under memory pressure. Scroll back up and it decodes the same image again. That is why the stall happens every single time you reach a section, not just the first time.

The specifics were ordinary and would look familiar on most stores.

What was on the page Sent at Displayed at Waste
Hero banner 2560px wide 352px slot 7x too wide
Five testimonial video posters 1320 by 2346 342px slot 4x too wide, tall source
Sixteen client logos up to 1600px wide 111px slot 14x too wide

Only 12 of 65 images carried a srcset, the attribute that lets a browser pick a size appropriate to the screen. Without it a phone gets the desktop original and no say in the matter.

41 MP

Image data before, on a 407px viewport.

9.5 MP

After, with no visible difference on any image.

3 to 0

Dropped frames during the same scroll, 88ms, 74ms and 83ms before.

Every replacement still covers its slot at better than two device pixels per CSS pixel, which is past the point where a human eye can tell the difference.

The part that stings

You are probably already sitting on the fix

Shopify and WordPress both generate resized copies of every image you upload. They sit on the server, already made, costing you nothing.

Most themes do not use them.

The theme drops in the original with a single src and no srcset, and every visitor on every device gets the full size file. The resized versions you paid for in upload time are never requested. On the store above, correctly sized copies of all 21 offending images already existed. Nothing was pointing at them.

Before you do anything clever, check whether the fix is already on your server waiting to be referenced.

Two minute check

How to measure your own store right now

Open your store on a desktop browser, press F12 for developer tools, go to the Console tab, and paste this.

[...document.images].filter(i => i.naturalWidth).map(i => ({
  file: i.currentSrc.split('/').pop(),
  actual: i.naturalWidth + ' x ' + i.naturalHeight,
  displayed: Math.round(i.getBoundingClientRect().width) + 'px',
  waste: Math.round(i.naturalWidth / Math.max(1, i.getBoundingClientRect().width)) + 'x too wide',
  srcset: !!i.srcset
})).sort((a,b) => parseInt(b.waste) - parseInt(a.waste))

You get a table of every image on the page, sorted by how oversized it is. Anything showing more than 3x too wide with srcset: false is costing you real time on mobile, no matter what it weighs.

Then narrow the browser window to about 400 pixels and run it again. That second number is the one that matters, because that is the phone.

The fix, in order

What actually moves the number

1. Serve the size the slot needs

Add srcset and sizes so the browser can choose, or point the theme at the resized copy directly. Aim to cover the slot at two device pixels per CSS pixel. A 350 pixel slot wants a 700 pixel image, not a 2560 pixel one.

2. Mark images for off thread decoding

decoding="async" tells the browser it does not have to decode on the main thread while it is trying to draw a frame. One attribute, no downside.

3. Decode ahead of the viewport, not at it

Lazy loading is good for bandwidth and bad for smoothness. The image arrives at the exact moment you reach it and the decode lands in the middle of your scroll. Start the work a screen or two early and the section is ready before the reader gets there.

4. Then, and only then, look at scripts

Render blocking JavaScript, app scripts on pages that do not use them and third party tags are all real problems. They are a different problem with a different fix, and chasing them while the phone is choking on 41 megapixels of bitmap will not show up in the numbers.

Why the generic advice keeps failing

Compress your images is advice about the easy half

File size is the one part of this that a phone handles well. Networks got fast. Mobile CPUs and mobile memory did not improve at the same rate, and decoding is CPU and memory work.

Every listicle repeats the same five tips because they are easy to write and easy to check off. They are not wrong. They are just finished before they reach the thing that is actually slowing the store down.

If you have already done all of it and the number has not moved, you are not doing it wrong. You have run out of the problems that generic advice covers.

Questions

The ones people actually ask

Does converting to WebP or AVIF fix this?

It reduces bytes, which helps on slow connections, and AVIF decoding is actually a little more expensive per pixel than JPEG. Neither format changes the pixel count, so neither fixes the decode cost. Format and dimensions are two separate decisions and you want both right.

What image width should I actually upload to Shopify?

Upload something generous, around 2000 to 2400 pixels on the long edge, so Shopify has room to generate every size it needs. The mistake is not the upload size, it is the theme requesting the original instead of one of the generated variants.

Will smaller images make my product photos look soft on retina screens?

Not if you cover the slot at two device pixels per CSS pixel. Above that ratio the extra detail is not resolvable by eye on a phone held at normal distance. Two times is the honest ceiling, not three or four.

Why does my desktop score look fine while mobile is bad?

Desktop has more memory, more CPU and bigger slots, so a 2560 pixel image is closer to appropriate and the decode is absorbed. The same page on a phone has one quarter of the slot width and a fraction of the memory headroom.

Do image optimization apps fix pixel dimensions?

Most do not. They compress and convert what you already uploaded, which is why people run one, save 60 percent of their bytes, and see no change in Largest Contentful Paint. Check whether yours rewrites markup to add srcset, because that is the part that matters.

How do I know whether images or scripts are my real problem?

Run the console snippet at a 400 pixel width. If the table comes back full of 10x and 20x rows with srcset false, images are your problem. If images are already close to their display size, stop reading about images and go and measure your apps.

Mohammad Usama

Founder · Shopify Plus Partner

Nine years on Shopify storefronts across jewellery, fashion, beauty, sports, lighting, luggage and food brands. I scope every project personally, and I am the one who tells you when a cheaper route would do the job.

Shopify Plus Partner since Dec 20205.0 ★ · 288 partner reviewsRawalpindi, Pakistan · working US, UK, AU hours

Measure first. Then decide whether you need us.

Run the two minute check above. If your images are already close to their display size and carrying srcset, you have just saved yourself paying someone to tell you that. If the table comes back full of 20x rows, send it over.

Newsletter

Feel free to reach out if you want to collaborate with us, or simply have a chat.

Email

USA

1001 S Main St, Ste 500 Kalispell, MT 59901, USA

Pakistan

Sector I‑14, Main Road I‑14, Islamabad, Pakistan

Made with ᥫ᭡ by Ecommhawks