The 400 KB hero

#html #images #performance

I spent most of a day in September getting a stylesheet from 96 KB down to 84 KB. I concatenated things and stripped comments. I found a chunk of dead CSS from a section that got cut and deleted it, which felt great.

12 KB! And then I ran the page through a waterfall for the first time in weeks and the homepage was 2.3 MB, of which about 1.9 was 4 images.

I did know, abstractly, that images are most of the weight of most pages. Everybody knows that and it’s in every talk. I optimize images at work most weeks, for that matter.

And I had still spent a day on 12 KB because in my head the image work wasn’t development. It was something I did in Photoshop in between the development. So when I sat down to do some performance work, I went straight to the stylesheet.

Let sleeping images lie

When I finally went and looked, it needed nothing I don’t already know how to do. I didn’t need a better format or a trick. I needed to open the JPEG and look at it.

The hero was 2400px wide because that’s what came out of the design tool at the size the comp was built. It was displayed at a maximum of 1200. So half of every dimension, which is 3/4 of the pixels, was being downloaded to be thrown away.

Resizing it to what it was actually displayed at took the file from just over 1 MB to about 280 KB. I could not tell the difference on any of my devices.

Then I looked at the quality. It had come out at whatever the default export was, which is somewhere in the 90s. JPEG quality has sharply diminishing returns past about 75 on lifestyle photos. Going to 75 took it to 140 KB.

I put the two versions side by side at full size and stared for a while and could not pick them apart. And I was trying to.

So that’s a megabyte down to 140 KB, on a single image, using 2 settings that have existed for 20 years. Versus my 12 KB of CSS. That ratio is the whole post really.

Metadata

Metadata is the other easy one. Photos out of a camera carry EXIF. Photos out of an editor carry an embedded color profile and sometimes a thumbnail and occasionally a full copy of the editing history. On one of the 4 images that was 60 KB of the file and it’s doing absolutely nothing for anybody visiting the site.

Run them through a lossless optimizer and it strips all of it without touching a pixel. On a project with a build step it’s a one-liner in Grunt or Gulp. Most of what I work on doesn’t have one so for me it’s a drag-and-drop app. Every image goes through it before it goes up now.

What even is retina?

This is the part I’m least confident about and the part that’s changing fastest so take it accordingly.

My first instinct was to serve everything at 2x so it’d look sharp on the newer phones and laptops, which doubles the dimensions and so quadruples the pixels. All of that went to people on phones, on mobile networks, to fix a problem they mostly didn’t have.

Then I overcorrected and served everything at 1x. The site looked unmistakably soft on those sweet, sweet retina devices.

I hold this loosely, but I’ve ended up thinking that for photographs a 2x image at a much lower JPEG quality is often smaller than a 1x image at high quality and looks better on both kinds of screen. The compression artifacts get scaled down along with everything else so you can be much more aggressive than feels comfortable. Something like quality 75 at 2x. It looks meh in the file browser but fine on the page.

That trick doesn’t work for flat graphics or anything with text in it, where the artifacts are easy to see. For those I’d be reaching for SVG anyway.

The proper answer is srcset, so the browser picks based on what it knows about the screen and the viewport which is more than the server knows. It’s been in Chrome for about a year. Firefox added it in May and Safari last month, and there’s a polyfill for the rest.

I’ve used it on one thing of my own. I’d like to say I’ve adopted it but I haven’t yet, mostly because on the sites at work the markup comes out of theme templates that aren’t mine to change. I think this is the thing I’ll look back on as obviously worth doing sooner.

hero.html
<img src="hero-1200.jpg"
     srcset="hero-1200.jpg 1200w, hero-2400.jpg 2400w"
     sizes="(min-width: 60em) 1200px, 100vw"
     alt="Sunrise over the harbor">
HTML

Don’t blame me, blame the process

Some of the images come through me and plenty of them don’t. They come from a designer, or from the client’s own folder of photos, or from a stock library. They arrive at whatever size they happened to be. And then they go into a CMS where whoever has a login will upload more of them for the next three years, at whatever size those happen to be.

So any fix I make by hand is a fix with a half-life. I can optimize the four images on that homepage beautifully and it’ll be undone by the next content refresh.

Which means the only version of this that survives is the one in the pipeline. That’s resizing on upload, a quality setting, and the optimizer somewhere nobody has to remember it. All of it is unglamorous infrastructure that gets done once and keeps working while nobody is paying attention. That’s the actual fix and it’s much less satisfying than the afternoon where I made a photograph 88% smaller and felt like a genius.

I need to start giving a damn

It turns out that I optimize what I think of as engineering. CSS counts and for some reason a hero image didn’t, even though I’d resized a dozen of them that month. So the heaviest thing on the page went unexamined for months while I sharpened something that was already fine.

I’d guess that generalizes. The unexamined part of any project is not the hard part. It’s the part that doesn’t feel like the real work and it stays unexamined precisely because everybody assumes it’s handled.

So, a small suggestion: open the network tab on something you work on and sort by size. Don’t optimize anything, just look. My guess is the top of that list will not be code.

Read similar posts

View posts by tag

#accessibility #agency #ai #careers #cross-browser-compatibility #css #culture #debugging #documentation #ecommerce #forms #git #html #images #javascript #performance #php #privacy #scss #security #shopify #small-print #tooling #typography #wordpress