DEV Community

Artur Smirnov
Artur Smirnov

Posted on

Your dropdown menu is 7 MB, and it ships on every page you have

A product page on a jewellery store weighs 8,293 KB. That is bad but unremarkable — plenty of stores are heavy, and the usual explanation is "it's a product page, it has photos."

Then I measured a second page on the same store, and the diagnosis changed completely.

7,011 KB of that product page is 27 theme images. Twenty-five of them are photographs in the dropdown navigation menu. And the same 7 MB is on the home page.

Identical. Not similar — the same set of files, the same bytes, on a page that has nothing to do with the product.

Why the second page is the whole finding

One page measurement can only tell you a page is heavy. It cannot tell you whose fault it is, and that distinction is the difference between a useful message and an annoying one.

Three explanations fit a single heavy page equally well:

  1. this particular page has a lot on it,
  2. the platform or theme is heavy by default,
  3. something shared is riding along on every page.

Measure a second, unrelated page on the same site and the three separate instantly. Whatever is identical between two unrelated pages is shared furniture. Whatever differs is the page.

Here the 7 MB was identical. So it isn't the product page, and it isn't a general platform tax either — it's a menu. Every visitor downloads twenty-five navigation photographs to look at a checkout page, a policy page, a 404.

That reframing is what makes it fixable. "Your product page is 8 MB" invites a shrug. "Your dropdown menu is 7 MB and it ships on every page" is a specific object with an owner.

The mechanism, and why the browser can't save you

Three properties, and it takes all three:

  • The files are around 2400 px wide, sitting in slots of roughly 300 px.
  • They carry loading="eager", so they're fetched immediately rather than when the menu opens.
  • None of them has a srcset.

That last one is the trap. A modern browser is perfectly willing to fetch a smaller variant — but only if you offer one. With no srcset, there is no smaller variant in existence, and the browser is obliged to take the 2400 px file to paint 300 px of it. This is not the browser being conservative. It has nothing else to choose from.

The same pattern, on a different store: 25 images larger than their slots, 5,480 KB total, and srcset on none of the 25. The banner is 3609×5414 — 19.5 megapixels, 1,432 KB — in a 340×460 slot. Five circular category thumbnails are 2380×2380, 210–291 KB each, in 74×74 slots. That's 32× wider than needed, per circle, for decoration.

Nobody chose any of this. Theme images get uploaded once at whatever size the source file happened to be, through an admin panel that accepts them without comment.

Do this on your own store, it takes two minutes

  1. Open your home page, DevTools → Network → Img, disable cache, reload. Note the total.
  2. Open a product page, or any page as unlike the home page as you can find. Note the total.
  3. Subtract. The overlap is what every visitor pays on every page.

Then, for anything big in the overlap, check two things in the Elements panel: the natural size against the rendered size, and whether the tag has a srcset at all. Overshoot plus no srcset is a file that literally cannot be delivered smaller.

Sort the overlap by size and fix downward. On both stores above, the top five files were most of the problem.

What I threw away, because it matters

I ran a detector across a batch of these stores, and roughly a third of what it flagged was wrong. Since the whole point is to tell owners true things, here is what fooled it:

  • "Six buttons have run off the right edge." It was a carousel. Off-screen slides are how carousels work.
  • "A row of products is faded out at opacity: 0.01." That was a scroll-triggered reveal, caught mid-animation because my script scrolled faster than a human ever would.
  • "This product card has no price." One store had 209 price elements on the page. My regex simply didn't recognise the Indian digit-grouping format.
  • "Overflow of 175 px at 390 px wide." At 320 px the overflow was zero — which is impossible for a genuine layout break, since narrower is always worse. The culprit was a hidden cart panel parked off-screen.

The rule I now use: a finding that gets better as the viewport gets narrower is not a layout break, and a signal from code is never the same thing as a working feature. Reproduce twice, and look at a screenshot before you believe any of it.

The general version

Most "your site is slow" advice fails because it can't assign responsibility. Owners on hosted platforms have heard it all and have a ready and often correct answer: that's just how the platform is.

The two-page subtraction is the cheapest way past that. It costs two page loads, needs no access to their account, and it converts an opinion into an object: this menu, these twenty-five files, this many megabytes, on every page you have.


I build browser tools where this kind of measurement is the job — parametric product configurators and engineering calculators, where the geometry and the costing come from the same parameters so they can't quietly disagree. Work at smirnov-artur.github.io/webgl, and I'm on Telegram at @smirnovarturr or at paladei702@gmail.com.

If you run the subtraction on your own store, I'd like to hear what was in the overlap. So far mine is winning at 7 MB of menu.

Top comments (0)