· 8 min read

Performance is a design decision

Speed is treated as an engineering concern, so designers hand over work that cannot be fast. Most of what makes a page feel slow was decided in the design file.

Speed is filed under engineering, which is why it keeps arriving too late to fix. By the time anyone runs a performance audit, the decisions that made the page slow were made months earlier, in a design file, by someone who was never told they were making them.

I do not mean this as a complaint about designers. I mean it literally: a large share of what a performance report flags is not a coding mistake. It is a design decision arriving in its final form.

The decisions that set the ceiling

Four things, chosen early, decide most of what a page can ever weigh.

The hero image. A full-bleed photograph at the top of a page is the largest thing on it and usually the element the browser measures as the point where the page appears loaded. Whether that image is a photograph, an illustration or a flat colour was a design decision, and it moved the number more than anything an engineer will do afterwards.

The typefaces. Every additional family and weight is a file that has to arrive before text can be drawn in the right shape. Two families at three weights each is a decision that costs real time on a slow connection. Nobody frames it that way in the review, where it is a decision about tone.

Whether the first screen depends on data. A layout where the top of the page is a personalised greeting cannot render until a request comes back. A layout where the top is static and the personalised part is further down can. That is a composition choice, made in a file, and it decides whether the page can be static at all.

How much moves before it settles. Every element whose size is not known in advance is a shift waiting to happen.

None of those get raised as performance questions during design, because performance is not on the agenda until later. That is the actual problem, and it is a version of the same gap I have written about in the handoff: the artefact arrives complete, and the constraints that should have shaped it show up afterwards as bug reports.

Layout shift is a design bug

Of everything in a performance report, layout shift is the one most obviously not an engineering problem. A page that moves under someone as it loads is not slow, it is rude, and it is the failure people actually describe when they say a site feels cheap.

The mechanism is nearly always the same: something arrived whose size was not reserved. An image without dimensions. A font swapping from fallback to real at a different width. A banner injected above the content. An advert. A component that renders nothing and then renders something.

Every one of those is fixable by knowing the size in advance, and knowing the size in advance is a design output. If a card can be 180 or 260 pixels tall depending on the length of a title, that variability was specified, and it will be paid for at load.

The version of this on my own site is the artwork. Every remote image gets pulled in-house at build time and measured, so the page has the real dimensions and can reserve the exact space before the file arrives. That is not a clever optimisation. It is the boring answer, and it exists because the alternative is a grid that rearranges itself while you look at it.

Reserve space for anything that can be absent. An empty state that occupies no height and then occupies 200 pixels is the same bug as an unsized image. If a section can be empty, decide what its empty height is, and decide it in the design rather than discovering it in production.

Skeletons, and when they are lying

Skeleton screens have become the default answer to "what do we show while loading", and they are frequently the wrong one.

A skeleton is a promise about shape. It says: content is coming, it will look roughly like this, and it will land here. When that promise is accurate it is genuinely good, because the eye settles into the layout before the content arrives and nothing jumps when it does.

When the promise is inaccurate it is worse than a spinner. Three skeleton rows followed by seven real rows is a shift you introduced deliberately. Skeleton rows followed by an empty state is a small betrayal: you showed someone content arriving and then told them there is none.

Two rules that have kept this honest for me. Only skeleton what you know the shape of. If the count is unknown, the shape is unknown, and a skeleton is a guess dressed as information. Do not skeleton anything fast. Under roughly 300ms a skeleton is a flash that reads as a glitch, and showing nothing is calmer than showing something twice.

The corollary is that a spinner is not a failure of imagination. For a genuinely unknown wait of unknown shape, it is the honest component.

Perceived speed is the only speed anyone has

Measured speed and felt speed come apart constantly, and where they disagree, the feeling is the thing people report.

A page that renders its structure in 300ms and fills in content over the next 400 feels faster than a page that shows nothing for 500 and then appears complete, even though the second finished first. Something happened, in response to something they did, quickly. That is the whole mechanism.

Which leads to the most useful design decision on the list: make the static part of the page independent of the slow part. Header, navigation, layout, headings and any content that does not come from a network call should be able to paint immediately. If those are inside the same loading boundary as a remote request, the whole page waits on the slowest thing in it, and that is a composition decision, not a caching problem.

The same logic applies to interaction. A control that responds on the next frame and reconciles a moment later feels immediate. A control that waits for confirmation before acknowledging the press feels broken at 200ms of latency, which is an ordinary mobile connection. Whether an action can respond optimistically is a design question about what happens when it fails, and it has to be answered in the design, because the failure state is a screen somebody has to draw.

Images are most of the weight, and most of the fix

If a page is heavy, it is usually images. Not code, images.

The parts that belong to design rather than engineering:

Whether the image needs to be there. The most effective compression is deletion, and a decorative photograph that carries no information is the easiest thing on the page to remove.

How large it actually renders. An image shown at 400 pixels wide does not need a 2000 pixel file. The number of production sites serving full-resolution assets into small containers is remarkable, and it is nearly always because nobody specified the rendered size.

Whether it is above the fold. Everything below can load lazily and cost nothing up front. Everything above must arrive first. That boundary is drawn in the layout.

Photograph or illustration. A flat illustration compresses to a fraction of a photograph. That is a stylistic choice with a weight attached, and the weight is never in the conversation.

Making it visible early enough to matter

The thing that changes outcomes is not a tool, it is putting the number somewhere a designer sees it while there is still time to act on it.

A budget stated in the terms of the work helps more than a score: this page loads on a mid-range phone in under two seconds, images above the fold total under 300 kilobytes, nothing shifts after first paint. Those are constraints a designer can design against. A score out of a hundred, delivered after handoff, is a grade on work already finished.

And the measurement has to happen on a device somebody actually owns. A design reviewed on a fast laptop over office wifi has been reviewed under conditions that no user shares. Throttle the connection once, look at the page you just approved, and the list of things to change writes itself.

The part that is hard to accept

Performance work is mostly subtraction, and subtraction is not what design reviews reward. A page with one typeface, no hero photograph and no entrance animation performs beautifully and does not look like anyone tried.

I do not think the answer is austerity. It is that the cost should be visible at the moment of choosing, so that a second typeface or a full-bleed photograph is a thing you decided to spend, rather than a thing that showed up in a report as somebody else's problem. Every performance decision worth making is a trade, and a trade you cannot see is not one you made.