Tailwind leading-* Handoff Mess — Design to Code
Figma says line height 24 on a 16 text style. The engineer applies text-base leading-6 and moves on. Another frame uses 150% line height. Someone else types leading-[150%]. Visual QA fails on half the pages because Tailwind’s leading-* scale is absolute rem sizes, not “Figma’s 24 means leading-6” in every theme — and percentage vs px gets mixed in handoff notes.
What leading-* actually sets
In default Tailwind, leading-6 is line-height: 1.5rem (24px at 16px root) — a fixed length, not 1.5 unitless relative to font-size. That matters:
| Utility | Computed idea (default theme) |
|---|---|
leading-none | 1 (unitless) |
leading-tight | 1.25 (unitless) |
leading-6 | 1.5rem (absolute) |
leading-[1.5] | unitless 1.5 × font-size |
leading-[24px] | absolute 24px |
If the designer changes font size to 18px but keeps “line height 24px”, absolute leading-6 stays 24px (ratio shrinks). Unitless 1.333 would keep a proportional look when type scales.
Convert Figma → Tailwind without guessing
Case A — Figma shows px line height (e.g. 24) and font size 16
- Ratio =
24 / 16 = 1.5 - Prefer
leading-normal(1.5) orleading-[1.5]for proportional scaling - Or
leading-6if you intentionally want 24px locked
Case B — Figma shows percent (e.g. 140%)
- Use unitless:
leading-[1.4] - Do not map 140% to
leading-7by superstition
Case C — Design tokens named “Body / 16 / 24”
Document the token as both size and line-height in code:
// tailwind.config.js
theme: {
extend: {
fontSize: {
body: ["1rem", { lineHeight: "1.5" }], // 16 / 24
"body-lg": ["1.125rem", { lineHeight: "1.5rem" }], // decide unitless vs rem deliberately
},
},
},
Then components use text-body once — no scavenger hunt for matching leading-*.
Handoff protocol that stops Slack ping-pong
- Designers specify font-size + line-height + whether line-height is fixed or relative.
- Engineers never “pick the closest leading-N” without computing the ratio.
- Shared type styles live in Tailwind
fontSizetuples or CSS variables, not ad-hoc class piles. - Visual QA compares computed
line-heightin DevTools to the token, not the class name.
Common mismatches
| Design note | Bad code | Better |
|---|---|---|
| 16 / 24 | text-base leading-4 | text-base leading-normal or text-body |
| 14 / 20 | text-sm leading-6 (too tall) | text-sm leading-[1.4286] or token |
| 12 / 16 | leading-4 with wrong text size | pair text-xs with matching LH |
| ”Tight” in Figma | random leading-tight | measure actual % |
Fluid type
If you use clamp() for font-size, absolute rem line-heights can look cramped at one viewport and airy at another. Prefer unitless line-height for fluid type, or define line-height inside the same clamp expression in CSS — utilities alone get messy.
Quick audit
# find lonely leading utilities that may be hand-tuned
rg "leading-\\[" src --glob '*.tsx'
Replace one-off arbitrary leadings with named fontSize styles when the same pair appears three times.
Review heuristic
Reject new leading-[Npx] in PRs when a fontSize token already encodes the pair. Capture the Figma ratio once; after tokens exist, stop hunting class strings. Designers who update a text style should change the token — not ping engineering to rewrite seventeen components that hard-coded leading-6.
Handoff mess is a unit problem: px vs percent vs rem vs unitless. Compute the ratio, encode it in a token, and stop treating leading-6 as a synonym for “whatever Figma’s 24 meant that day.”