Vertical spacing
Skill monikazapisek/design-engineering-playbook/skills/typesetting-engine-skillset/vertical-spacing
A practical operating system for senior UX/UI and Product Designers who want to use advanced AI across the full product lifecycle: strategy, design systems, prototyping, project management, and design-to-code workflows.
npx -y skills add monikazapisek/design-engineering-playbook --skill vertical-spacingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when computing or fixing vertical spacing (margins, padding, Auto Layout gap) between text blocks or components against a grid base, accounting for vertical-trim state on any text layers involved.
SKILL.md
10.6 KB, as published. Nobody here has run it
Vertical Spacing
Purpose
Compute vertical spacing (margin, padding, Auto Layout gap) as clean multiples of a grid base, applying the proximity rule (elements that relate should sit closer together than elements that don't), and correcting for vertical-trim state so the optical gap matches the set gap.
When To Use
- Reviewing or defining spacing for a card, section, article, or form.
- Fixing an Auto Layout frame in Figma where gap/padding look inconsistent or off-grid.
- Not for spacing within a single line of text (that's
text-typesetting) or column width (line-length-optimizer).
Inputs
grid-base: default8px(or4pxfor denser UI); confirm which the project uses rather than assuming.component-type: card / page section / article / form.hierarchy-level: compact / standard / spacious.base-line-height(LH): the resolvedline-heightof the body text in the flow — required for Workflow step 5 (paragraph/list rhythm), since those gaps are defined as a fraction of it, not as fixed pixel values.- If available: Figma Auto Layout properties (see Figma Node Integration) and the
textLeadingTrimstate of any text layers inside the frame.
Outputs
- Spacing values, all multiples of
grid-base(e.g. 8, 16, 24, 32, 48, 64, 96). - CSS (flex/grid
gap, margin) or Tailwind utility classes, matching whichever convention the project already uses. - A note on any vertical-trim-driven adjustment (see Workflow step 3).
- For paragraph/list flow:
paragraphSpacing, list-to-paragraph gap, and list-item gap, each shown as both theLH-fraction formula and the resulting pixel value (see Workflow step 5).
Workflow
-
Snap every value to
grid-base. Reject or round any spacing value that isn't a clean multiple — flag existing off-grid values found in input CSS rather than silently leaving them. -
Apply the proximity rule. Spacing above a heading (separating it from the previous, unrelated block) should be noticeably larger — roughly 2–3× — than the spacing below it (to the body text it introduces). E.g.
margin-top: 48px/margin-bottom: 16pxon a heading, not symmetric values on both sides. -
Vertical-trim correction (critical when text is involved):
- If the text layers in this spacing context have vertical-trim off (default), the visually perceived gap is smaller than the set
gap/marginvalue, because the font's built-in leading eats into it — e.g. a setgap: 16pxoptically reads as ~11px. Either compensate by increasing the set value, or (preferred) recommend turning vertical-trim on for those text layers so the set value and the optical value match exactly. - If vertical-trim is on, the set spacing value is the true optical distance from baseline/cap-height to the next element — no compensation needed; this is the state to prefer for new work.
- Always state which assumption is in effect — don't emit a spacing recommendation without saying whether it assumes trim on or off, since the correct pixel value differs between the two.
- If the text layers in this spacing context have vertical-trim off (default), the visually perceived gap is smaller than the set
-
Report, don't silently rewrite a stylesheet or Figma frame unless asked to apply directly.
-
Paragraph and list rhythm — all derived from
LH(body text line-height), not fixed pixel guesses:Relationship Formula Example (LH = 24px) Between paragraphs ( paragraphSpacing)0.50–0.75 × LH12–16px Between a list block and the surrounding paragraph (before and after) same as paragraphSpacing— treat the whole list as one paragraph-equivalent unit12–16px Between items inside one list ( List_Item_To_Item_Gap)0.25–0.33 × LH— deliberately tighter thanparagraphSpacing, so the list reads as one cohesive block (Gestalt proximity) rather than a series of unrelated paragraphs6–8px Bullet/number to item text (horizontal indent) fixed optical distance, not an LHfraction — onegrid-basestep or1ch(the width of a "0" in the running font), whichever the project's existing spacing convention prefers8px - Don't apply
paragraphSpacingand first-line paragraph indent (1emtext-indent) together — pick one convention per project. If the input already shows one in use, match it rather than introducing the other. - Snap the computed
LH-fraction results togrid-base(step 1) where the two don't conflict; ifgrid-baseand theLH-fraction range don't intersect cleanly (e.g.LH = 22px→ 0.5–0.75× = 11–16.5px, andgrid-base = 8only offers 8 or 16), prefer the value inside theLH-fraction range over forcing a grid-base multiple — state which constraint won when they conflict, rather than silently picking one. - This step depends on
text-typesetting'sline-heightoutput — ifbase-line-heightisn't given, ask for it or compute it via that skill first rather than guessing a round number.
- Don't apply
-
Figma margin-collapse guard (a real Figma-specific gotcha, not a CSS concept): Figma's
TextNode.paragraphSpacingonly adds space below a paragraph, not above the next one — there's no browser-style margin-collapse behavior reconciling two adjacent blocks' spacing. If a heading node (H2, say) directly follows a paragraph node, the paragraph'sparagraphSpacingalone is usually too small a gap above a heading (it was sized for paragraph-to-paragraph rhythm, not paragraph-to-heading), and the heading will visually "stick" to the text above it.- Fix: don't rely on the paragraph's trailing
paragraphSpacingfor this transition. Explicitly override the space above the heading — either via the parent Auto Layout frame'sitemSpacingfor that specific gap (if using per-item spacing /itemReverseZIndexgap overrides), or by giving the heading node its own leading space, sized to:Margin_top_heading = 1.5 × LH_body - This is larger than the standard heading proximity ratio in step 2 specifically to counteract the missing collapse behavior — don't also apply step 2's 2–3× ratio on top of this value; they solve the same problem, use the larger of the two, not both stacked.
- Fix: don't rely on the paragraph's trailing
Figma Node Integration
When running with Figma access, work against the selected FrameNode:
- Read:
layoutMode(must beVERTICALorHORIZONTAL— ifNONE, this isn't an Auto Layout frame and gap/padding don't apply the same way; report that first),itemSpacing(=gap),paddingTop/paddingBottom/paddingLeft/paddingRight. - Also read
textLeadingTrimon any childTextNodes — this is the input to Workflow step 3. Don't compute a spacing verdict for a frame containing text without checking it. - Paragraph/list frames: read
TextNode.paragraphSpacingandTextNode.paragraphIndentdirectly when the node is a body-copy text node with multiple paragraphs — Figma exposes these as native text-node properties, not just Auto LayoutitemSpacing, so check which one the content actually uses before recommending a fix. - Verdict: if
itemSpacing/padding aren't multiples of the confirmedgrid-base, flag each offending value with the nearest clean multiple. - Alert pattern for missing trim: "Wykryłem brak vertical trimu w warstwach tekstowych w tej ramce. Przy
gap: {itemSpacing}pxrzeczywisty odstęp optyczny to ok. {estimate}px. Rekomenduję włączenie Vertical Trim: Cap height dla precyzyjnej siatki {grid-base}px." — give this as the concrete alert text when trim is off and the frame is otherwise on-grid. - Action back to Figma: set
itemSpacing/padding, orparagraphSpacing/paragraphIndentfor text-node-native rhythm, ortextLeadingTrimon child text nodes, only on explicit request — never silently.
Quality Checklist
- Every emitted spacing value is a stated multiple of
grid-base. - Proximity rule applied asymmetrically around headings (top ≫ bottom), not symmetric padding by default.
- Vertical-trim state checked for any text-containing frame before giving a final gap value; assumption stated explicitly if unknown.
- Off-grid values found in existing input are flagged, not silently left or silently "fixed" without saying so.
- Paragraph/list rhythm values (step 5) shown as both the
LH-fraction formula and the resulting px — never a bare pixel number with no derivation. - List-item gap is visibly tighter than
paragraphSpacing(0.25–0.33×LH vs. 0.5–0.75×LH) — never emitted equal or reversed. -
paragraphSpacingand first-line indent not both recommended together; matches whichever convention the input already shows. - Figma writes (if any) only happen on explicit request.
- Cross-reference to
text-typesettingnoted when the fix is really "turn on vertical-trim" rather than a spacing-value change.
References
- Latin, M. (2017). Better Web Typography for a Better Web. — mathematical treatment of vertical rhythm and grid-base spacing.
- Butterick, M. Practical Typography. — critique of rigid baseline-grid enforcement in favor of flexible, grid-base-multiple padding/gap.
- Wertheimer, M. (1923). Gestalt principle of proximity — elements spaced closer together are perceived as grouped/related; the basis for list items sitting tighter than paragraphs.
- Bringhurst, R. (2012). The Elements of Typographic Style (4th ed.). Hartley & Marks — paragraph spacing and first-line indent as alternative (not combined) conventions, both derived from line-height rather than arbitrary pixel values.
- Figma Plugin API Docs:
FrameNode.layoutMode,FrameNode.itemSpacing,FrameNode.paddingTop/Right/Bottom/Left,TextNode.textLeadingTrim,TextNode.paragraphSpacing,TextNode.paragraphIndent. - Related skills:
text-typesetting(vertical-trim and line-height source of truth),line-length-optimizer(horizontal measure — different axis, same text blocks).