Content scaling — use-case guide
Hold Shift and drag a corner handle on any node to scale it. Where a plain resize moves a box's edges and lets the children reflow at their own size, shift+corner is a true proportional scale: the aspect-locked drag produces one uniform factor and every px-denominated value in the subtree rides it, so the composite keeps its proportions and orientations — the "this mockup is tiny next to that one" fix. On a leaf the subtree is the node itself: a text node's type scales with its dims, and style geometry (radius, borders, shadows) follows on every node type. A live percentage badge (relative to gesture start) rides the cursor.
Try it: draw a box (B), put a couple of boxes and a text node inside, select the parent, hold ⇧ and drag a corner handle.
What scales (one factor, everything)
- Fixed widths/heights — including the dragged box's own.
- Absolute children's x/y (so nested compositions keep their geometry).
- Margins of everything inside; flex gap and padding; grid row/column gap.
- px lengths inside grid track templates (
200px 1fr→300px 1fr; fr/%/auto pass through untouched). - Type: font size and letter-spacing.
- Style geometry: corner radius (single or per-corner), border width, outline width + offset, shadow x/y/blur/spread, px blur and backdrop-blur.
Scaled values round to tenths of a px — fine enough that small elements hold their proportions, coarse enough that the inspector stays readable.
What deliberately doesn't
- Rotation — orientation is preserved, not multiplied.
- Unitless line-height — it's a multiplier; it follows the font size.
- Fit/fill dimensions — layout scales them for free; their retained px is dormant and stays put.
- %/deg filters (brightness, saturate, hue-rotate…) — no px in them.
- Other styles (raw CSS) — the escape hatch is opaque by contract; rewriting numbers inside it could mangle values that aren't lengths.
- The dragged box's own margin — that's spacing against the outside world, not content.
- Zero values — a multiply can't move them (and a bound 0px spacing field keeps its binding for the same reason).
Interaction semantics
| Surface | Act | Effect | Undo / cancel |
|---|---|---|---|
| Corner handle, any node | ⇧-drag | Aspect-locked scale of the node + its entire subtree; % badge rides the cursor | One step; Esc restores everything |
| Corner handle, text node | ⇧-drag | Same — font size and letter-spacing ride the factor with the dims | One step; Esc restores |
| Corner handle | ⇧⌥-drag | Same scale, from the node's center | One step; Esc restores |
| Mid-drag | release ⇧ | Scaled values snap back to start; the box continues as a plain resize | Still one step |
| Mid-drag | press ⇧ | Upgrades to scale — factor computed from gesture-start values | Still one step |
| Edge handle (n/s/e/w) | ⇧-drag | Plain resize — scale is corner-only | — |
| Bound gap/padding/margin inside | scaled | Detaches the spacing-token binding + writes scaled px together (a stale binding would lie) | One step restores binding + px |
Guide snapping is off under ⇧ (a one-axis snap would break the lock), same as plain aspect resize. ⌘ mid-gesture keeps its usual meaning elsewhere.
Known limits (by design)
- px values inside Other styles (raw CSS) don't scale — the same escape-hatch opacity as everywhere else; check that section after scaling imported content.
- Browsers render fractional font sizes slightly differently across engines — at extreme downscales, tenth-rounding may read a hair off.
- There is no plain aspect-lock-without-scale on corners anymore; type exact dims in the inspector if you need a ratio-true resize that keeps style geometry fixed.