The five floors
The numbers live in one place in the registry,
BUNDU_FLOOR.spacing in
lib/tokens/roles.source.ts. The registry serves them as the same five numbers everywhere
(see one set of numbers). No brand pack and no density layer lowers a
floor; the one exception is the legacy opt-out, which steps out of it.
Why
The reasons are the Bundu floor’s: older users, people reading outdoors in glare, people on small and cheap phones, and the mis-taps that cramped controls cause. A control with its neighbour 2px away is easy to hit by mistake, text that touches its container edge is hard to find in glare, and a line height under 1.5 is harder to track for anyone who reads slowly or with low vision. The spacing floor is design intent backed by the registry’s tests (below), not a measured result: no pilot or user study on this site shows its effect.How a component meets it
The token layer carries the floor, so a component that sets nothing already meets it.- The variables
--inset-floor,--gap-floorand--leading-floorare in:rootofmzizi-tokens-globals.css. They are also registered as fixed size roles, so the platform token files carry 14 and 7 as they carry 49. - The base layer enforces defaults for an element that sets nothing:
padding-inline: var(--inset-floor)on a barebutton,select,textareaor textinput;padding: var(--inset-floor)on a bare text surface (a nativedialog, a[popover], an alert, a tooltip, a card with no structured children);gap: var(--gap-floor)on a list, group, toolbar or tablist; andline-height: max(var(--lh-body), var(--leading-floor))onbody. - It steps aside, on purpose, for an icon-only button, an empty element, a fixed square
(
size-*), a calendar day, the native checkbox, radio, range, colour and file inputs, and a card whose padding lives on itscard-headerandcard-contentchildren (padding both would pad twice). - A utility is your own value.
p-3orgap-1on the element wins over the base layer, even when it is under the floor, so an explicit value is held to the floor only by a check you run (the CLI below); the registry’s contract tests are not yet onmain. Writep-inset-floor,px-inset-floororgap-gap-floorto take the floor itself. - A control’s block axis is held by its height. 14px of block padding does not fit a control drawn at 28px, so for a control the inset floor is the inline axis, and for a surface it is both axes.
- The 7px gap is measured between visible edges. The registry says hit regions may touch
but not overlap. The 49px
hit-areaoverlay may reach into the gap, though: where two covered controls sit closer than 49px apart their overlays overlap and the later sibling wins the overlap, so keep gaps at the floor or above.
How it is enforced
What is on registrymain (4.24.0) and what is still to come are different, so the table
separates them. The registry’s 4.24.0 changelog says the component audit, contract and Rust
parity, the geometry guard and the lint-style tests “follow in their own pull request”.
In an app: the CLI
@nyuchi/mzizi-cli 0.8.0 adds mzizi check [path...], which enforces the floor over your
source. It is merged on the agent-tools staging branch and ships with that package’s next
release. As of 4 November 2026 the latest version on npm is 0.7.0, which has no check
command; run npx @nyuchi/mzizi-cli --version to see what you get.
var() or
calc(), it does not check vertical padding other than zero, and a tight line height on a
display heading needs an exception comment (below). Those limits are the CLI’s own, stated in
its README.
The exception comment
A violation that is deliberate carries a comment with a reason, on the same line or the line before (in CSS, or the comment syntax of the language you are in):-file form that covers the
whole file.
The legacy opt-out
data-mzizi-sizes="legacy" on the root element, the alias the Bundu floor
describes, also sets --inset-floor, --gap-floor and --leading-floor to 0, 0 and 1. The
registry describes the base-layer rules above as a no-op then. A rule that still reads a
variable set to 0 applies 0, so look at your native dialogs and popovers after you opt out. It steps out of the floor. Use it only to take the registry version
before you have moved your layouts, and remove it as soon as you have.
One set of numbers
The floor is read from the registry, not typed in each place:
If a surface disagrees with
BUNDU_FLOOR, the surface is wrong: change it upstream in the
registry.
Sources
The registry’ssizes-and-density.md
holds the rule and its tests, and
mzizi-registry#617 the owner’s ruling
and the list of surfaces it lands on.