Design · Speed

A screen that waits before it opens

Tap a button, nothing happens, nothing happens, then a panel appears. The panel was waiting for the server before it would show itself — and every one of those silent seconds reads as a broken button.


Two panels in our own software had the same shape of bug this week, found a day apart. Tap the control, and nothing appears until a request has come back. Then the whole thing arrives at once, fully populated.

It looks fine on a fast connection, because the gap is forty milliseconds. It is indistinguishable from a dead button on a bad one.

What the code was doing

Both were written the same natural way: fetch what the panel needs, then build the panel with the answer. One line after the other, perfectly readable, and wrong in exactly one respect — the order.

Flipped, they open in the same instant as the tap and fill when the answer lands. The panel's frame, its heading and its close button are all things we already know; none of them needed the server's permission to exist.

Skeletons, not spinners

What goes in the gap matters too. A spinner tells you to wait. A set of grey blocks the size and shape of the rows that are coming tells you what you are waiting for — and, more usefully, means nothing jumps when the content arrives. The layout is already the right shape.

One detail worth copying: in the ordinary case, where the data is already in hand, we draw the real rows immediately and no skeleton is ever seen. A loading state that flashes up for one frame when there was nothing to load is a flicker, not a courtesy.

It is an old rule here

Our own working notes have said for months that a panel which fetches on open must open instantly with a loading state. Both of these predate that note and nobody had gone back through the ones already written.

That is the honest lesson. Writing a rule down does not apply it to the code you already have. Somebody has to open the screens.


Try it on tonight’s service.

Nothing to install, no card. Not better by the weekend? Close the tab.