Loading must keep the button’s size stable
Aliases: layout shift · spinner replacement · stable loading width
What it is
On loading, the label is often replaced by a spinner or “Submitting…”. If the new content is shorter or taller than the original, the button’s width and height jump and the neighborhood twitches. That twitch can slide Cancel under the finger, or let the still-pressed key slip away. Loading should swap content inside the original box. Size stability exists so a lock interval does not manufacture a new miss.
Why it happens
After press, the finger may not have left and gaze is still on that rectangle. If the rectangle shrinks, the hit region shrinks with it, the fingertip’s relative position slides outside the box, and the lift lands on whatever is now behind—Cancel, another submit, even the page outside a dialog. If the rectangle grows, it may shove the right-hand button or wrap the row, and the thumb’s target map dies. A square spinner’s aspect is nothing like “Pay ¥128.00 now”; a shrink-wrapped control will almost always jump. Stable size treats loading as a skin of the same control, not as a different control.
Studying it
Record geometry at the submit instant: the button’s bounding box, displacement of neighbors, the hit target on lift. Compare width-follows-text with a min-width locked to the rest state.
Independent variables: loading content (spinner only / spinner plus a short word / original label plus spinner), whether the button is fixed-width, whether contact remains until lift. Dependent variables: layout-shift pixels, lift mis-hits, neighbor activations.
A mouse click that leaves on press underestimates the problem because displacement happens after the pointer is gone. A held touch is closer to the field.
Where it stops holding
A long localized string replaced by a short “Please wait” will look sparse in a wide desktop button; prefer the spare space over shrinking onto a neighbor. In a button group, one control growing shoves the set—fix the group’s widths or swap only an inner icon. A full-page skeleton is not button loading; stability constrains this control.
Applying it
- Compute a minimum width from the longest rest label or from the content box; loading replaces the interior, not the outer box.
- Center a spinner with type on the vertical axis; do not grow height to fit the icon.
- Do not animate the button in with a scale; scale is a size change on purpose.
- Verify by lining up the four edges in slow-motion capture at submit. If an edge moves, or lift hits Cancel, size is not stable.