Ten steps, from things that touch to things that are apart. Every one moves together when the density changes, so a screen is dense or roomy as a whole rather than in pieces. Hover the bars to space them evenly.
A spacing scale is the one part of a design system you can print at life size and have it mean exactly what it means on screen. Below is the ladder, drawn at 100 per cent.
It doubles roughly every two steps, which is enough resolution to separate a label from its icon and a section from the next one without offering forty values nobody can choose between. Ten is a number a person can hold.
Each row shows its step twice: once as something and once as nothing. They are the same measurement, and the second one is the half people forget to check.
Every size in the product is a rem multiplied by the density setting. Padding, gaps, radii and type all
read the same variable, so changing it is not shrinking the text inside the same boxes — it is a denser interface.
Five steps, from −2 to +2, and the app opens at 0. Someone who wants more room moves up, someone who wants more on screen moves down, and the whole interface follows either way, holding its proportions at every step. The range is deliberately short: two notches is enough to matter and not enough to break a layout.
Every pixel figure in this system is quoted at step 0, so the documentation and a default screen agree. A value measured in the inspector is the value in the table.
One formula, and no viewport override. It is tempting to tighten things up when a window is narrow, but a cramped window is already short of room and taking space out of it makes it harder to use rather than easier. Anyone who wants more on screen has the setting. On touch it would be worse than unhelpful: a finger needs a larger target, not a smaller one, so shrinking an interface because the screen is small is exactly backwards.
| Step | Scaling | space-5 | ui | |
|---|---|---|---|---|
| -2 | 0.90 | 14.4px | 11.7px | tighter, more on screen |
| -1 | 0.95 | 15.2px | 12.3px | |
| +0 | 1.00 | 16.0px | 13.0px | the default. Every figure in this system is quoted here |
| +1 | 1.05 | 16.8px | 13.7px | |
| +2 | 1.10 | 17.6px | 14.3px | roomier |
Everyone matching the rules below is added automatically.
:root {
--fc-scale-step: 0; /* -2 … +2, the user's */
--scaling: calc(1 + var(--fc-scale-step) * 0.05); /* 0.90 … 1.10 */
}Density is not a text size. It is how close together a person wants to work.
Four corners, each one a step from the spacing scale, so a card's radius and its padding are related numbers rather than two decisions. The fifth is not a size at all — a pill is a shape, and it stays a pill at every density.
Badges, chips, small indicators
Inputs, buttons, menu items
Cards, panels, popovers
Dialogs, drawers
Pills and avatars. Not a size, a shape
Three things get mistaken for spacing, and keeping them out is what lets ten steps be enough.
Type sizes are not spacing steps. They live on their own ladder, with their own leading and tracking and face. A rung and a gap are different kinds of measurement that happen to be expressed in the same unit.
Layout widths are not spacing steps. A pane that is 720px wide is a layout decision made once for that pane. Putting it on the spacing scale implies it belongs to a progression, and invites someone to reach for the step next to it.
A one-off is not a step. If a value appears once, it is a number in a component, not a token. A scale earns its place by being reused.
One scale of forty-nine tokens becomes ten spacing steps, four radii, and two things that were never spacing. This section is here for the migration and comes down once it is done.
| Today | Becomes | Why | |
|---|---|---|---|
| viewport override | --scaling changes at 1536px | gone | Every dimension jumped 11 per cent at one width, and it shrank phones, where a target needs to grow. |
| 49 size tokens | one scale for everything | space-0 → space-9, plus radius | Ten steps for gaps and padding. Type has its own ladder. Fixed dimensions stop pretending to be spacing. |
| size/1-75, size/2-5 | 7px and 10px | gone | Neither is a step in any progression. Both were a value someone needed once. |
| size/2-75 … size/3-5 | 11, 13 and 14px | the type ladder | These are type sizes living in the spacing scale. They move to the rungs that own them. |
| size/140 … size/306 | 560px to 1224px | layout widths | Seven tokens above 400px, each used once or twice. A pane width is a layout decision, not a spacing step. |
| radius/fixed/md, /lg | 16 and 20px | gone | Duplicates of radius/lg and radius/xl under a second name. |
Nobody building a screen measures anything. They ask for the gap between rows or the padding of a card, and it arrives at whatever density the person reading it has chosen.