lazyload.md3 min read

← index

You do not need to know how big the screen is

Native lazy loading, and who is supposed to do the measuring.

3 min

The objection to screen relative units for images is that you can’t use them because you don’t know how big the image will be and you don’t know that because you don’t know the size of the screen.

You don’t need to know. That’s the entire point of the units. When you set something to 25vh you’re telling the browser to use a quarter of the viewport height and the browser is the thing that knows what a quarter of the viewport height happens to be on this device at this moment. You’ve handed the measuring to the only participant with the measurements.

That’s useful in a specific way that matters here. If you want four images stacked vertically, the browser now knows it needs to reserve a box a quarter of the screen high and it can put that box in the layout before the image has arrived. Nothing shifts when the image loads. You’ve avoided the layout thrash that makes a page jump around while you’re trying to read it and you did it without measuring anything yourself.

The other half of the objection is that if JavaScript is still needed then the spec is worthless. That’s not quite what’s on the table. The parent case was wanting to change the width and height attributes of an image when the user resizes their browser and the resize event is precisely what exists for that. Wanting to react to a resize is a reason to use the resize event rather than evidence that the platform has failed you.

There’s a whole ladder of options underneath that, and which rung you want depends on what you’re trying to do. A fixed size image can have fixed width and height attributes and an image that should scale with the viewport can use relative units. Something that needs to be fixed on some devices and relative on others can be done with media queries, mixing and matching without a line of script. And if you genuinely need to compute the attributes at runtime, then yes, you write some JavaScript and that’s a normal thing to do rather than an admission of defeat.

The part worth being clear about is what the new specification actually buys. Lazy loading images with JavaScript worked perfectly well before this landed, and plenty of people had it working and the libraries were mature. The catch was that you needed the JavaScript which meant the weight of the code and the parse time and the dependency and the behaviour when script fails or is slow to arrive.

Getting the basic version of that behaviour from an attribute in the markup removes all of it for the common case. Not every case, and not the elaborate ones where you’re doing something clever with thresholds or placeholders. The common case which is the great bulk of images on almost every page anyone ships, where somebody just wants the images below the fold to wait their turn.

That’s a good trade and it’s the shape most platform features take and they don’t remove the need for script at the top end. They remove the need for script at the bottom end, where most of the web lives and the argument that they haven’t solved everything tends to come from people working at the top.

The wider habit here is worth naming because it comes up well beyond images. A lot of frontend work is people recomputing something the browser has already worked out, usually because the platform way of asking for it is less obvious than the arithmetic and the arithmetic feels more like programming. The result is code that goes out of date whenever the layout changes and that quietly disagrees with the browser at exactly the moments you would most like them to agree.

When you find yourself measuring the viewport, it’s worth a minute checking whether you could just describe what you want instead.