Responsive typography
Skill jpoindexter/typography-skills/skills/responsive-typography
Typography skills for AI coding agents — 20 focused skills + a /type router, extracted from 10 canonical typography books and reconciled against WCAG 2.2 and current browser behavior.
npx -y skills add jpoindexter/typography-skills --skill responsive-typographyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 11 days oldThe repository was created 11 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 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 type must adapt across viewports, containers, or devices — fluid sizing with clamp(), breakpoint jumps, text that overflows or shrinks illegibly on mobile, headings that wrap badly, or a scale that works on desktop and collapses on phone. Also use when building a type system intended to be resolution-independent.
SKILL.md
8.3 KB, as published. Nobody here has run it
Responsive typography
The shift Brown argues for: stop designing screens and start designing relationships that hold at any size.
1. When to invoke
- Type sizes must change across viewports or container widths.
- Headings wrap badly, overflow, or shrink below legibility on small screens.
- Building a type system meant to work without per-breakpoint overrides.
- Migrating from fixed breakpoint steps to fluid sizing.
Do not invoke to choose the base size (body-text-and-reading) or the ratio
(hierarchy-and-scale). This skill adapts a scale you already have.
2. Required context
- The existing scale and body anchor.
- Minimum and maximum viewport (or container) widths you support.
- Whether sizing should key off the viewport or the container — a card in a sidebar should respond to the sidebar, not the window.
- Whether the component is reused at multiple widths.
- Whether users can zoom, and whether Dynamic Type / user font-size preferences apply.
3. Invariant principles
- Design relationships, not screens. A fixed size at each breakpoint is a set of disconnected designs. Define how size, spacing, and measure move together.
- Everything is interdependent. Change viewport → measure changes → the size and line-height that suited that measure no longer do.
- Never disable user zoom.
user-scalable=noandmaximum-scale=1violate WCAG 1.4.4. - Never size type in raw viewport units alone.
font-size: 4vwdoesn't respond to user zoom at all, because zoom doesn't change viewport units proportionally. Always combine with a rem term. - Line-height must be unitless so it scales with the font size it inherits.
- Larger viewport does not simply mean larger type. It means a longer available measure, which may call for a wider column, more size, or both — decided visually.
4. Context-dependent heuristics
Fluid sizing with clamp(). The correct shape is:
/* min, preferred (must contain a rem term), max */
font-size: clamp(1.5rem, 1rem + 2.5vw, 3rem);
The 1rem + term is not decoration — it's what keeps the text responsive to user
zoom and font-size preferences. clamp(1.5rem, 4vw, 3rem) fails WCAG 1.4.4 in the
fluid band.
Fluid vs. stepped — a real choice, not a default.
| Use fluid when | Use breakpoint steps when |
|---|---|
| Type should feel continuous across sizes | Sizes must land on exact token values |
| Display/hero type spanning a wide range | Dense UI where an off-token size is a bug |
| Few levels, editorial character | Many levels that must stay distinguishable |
| You can verify the whole band visually | You need discrete, auditable states |
Fluid type is hardest to verify because it has infinite states. Check the two endpoints and several points in between — defects usually live mid-band.
Container queries over media queries for components. A component reused in a main column and a narrow sidebar should key off its container:
.card { container-type: inline-size; }
@container (min-width: 30rem) { .card h2 { font-size: 1.5rem; } }
This is the fix for "the card looks right on the page and wrong in the sidebar."
Scale the ratio, not just the sizes. A 1.333 ratio that reads well on desktop is often too dramatic on a phone, where the largest step overwhelms a narrow column. Compressing the ratio at small sizes usually beats compressing every size independently.
Measure is the real constraint. As the viewport grows, don't let the column
grow with it indefinitely. Cap the measure (max-width in ch or rem) and let
the margins absorb the rest.
Small screens have a floor. Roughly 40 CPL is normal on a phone at default size; don't shrink type to buy characters. Below ~16px body on mobile, tap-target and legibility problems arrive before typographic ones.
5. Failure patterns
| Pattern | Cause | Fix |
|---|---|---|
| Text doesn't grow when the user zooms | vw-only sizing | Add a rem term to the clamp() preferred value |
| Hero heading is fine at 1440 and 375, broken at 900 | Only endpoints tested | Sweep the middle of the band |
| Card correct on page, wrong in sidebar | Media queries on a reusable component | Container queries |
| Line-height fine large, cramped small | Fixed line-height, or a unit value | Unitless, and consider a larger ratio at small sizes |
| Column keeps widening on ultrawide until unreadable | No measure cap | max-width in ch/rem |
| Body shrunk on mobile to fit more words | Optimizing CPL over legibility | Accept ~40 CPL; keep the size |
| Fluid sizes land off-token | Fluid applied to dense UI | Use stepped sizes for UI, fluid for display |
| Two-word heading becomes 3 ragged lines | No wrap control | text-wrap: balance |
6. Evaluation procedure
- Render at min supported width, max supported width, and ≥3 points between.
- At each, count CPL and confirm the measure is defensible for that width.
- Zoom to 200% at each. Text must grow. If it doesn't, a
vwterm is unguarded. - Test the component in every container it's reused in, not just every page.
- Check the largest heading at the narrowest width for wrapping and overflow.
- Confirm every
line-heightis unitless. - Confirm no
user-scalable=no/maximum-scalein the viewport meta. - Re-check hierarchy at the narrowest width — levels often collapse there.
7. Output format
Strategy: <fluid | stepped | hybrid> — because <reason>
Viewport band: <min> → <max>
Sizing: <role>: clamp(<min>, <rem term> + <vw term>, <max>)
Query type: <viewport | container> — because <reason>
Measure cap: <value>
Verified at: <list of widths tested>
Zoom 200%: <pass/fail>
Unverified: <what wasn't rendered>
8. Examples
Marketing hero, 375→1440.
Fluid suits it — one level, wide range, editorial character.
clamp(2rem, 1.25rem + 3.5vw, 4rem). The1.25rembase keeps it zoom-responsive; the3.5vwterm does the travel. Verified at 375/600/900/1200/1440 — at 600 the heading was breaking to three lines with a one-word last line, so addedtext-wrap: balance. At 200% zoom the text grows correctly.
Dashboard, same product.
Stepped, not fluid. Sizes must stay on token values so an off-scale size is detectable as a bug, and the dense scale's steps are small enough that fluid interpolation would blur adjacent levels. Two breakpoints, both landing on existing tokens.
9. Counterexamples
- ❌
font-size: 4vw— ignores user zoom entirely. WCAG 1.4.4 failure. - ❌
clamp(1rem, 3vw, 2rem)— same failure inside the fluid band; the preferred term needs a rem component. - ❌
<meta name="viewport" content="width=device-width, user-scalable=no">— never. - ❌ "Fluid type means we don't need breakpoints at all." — Layout still changes structurally; fluid sizing doesn't reflow a grid.
- ❌ "It works at 375 and 1440, ship it." — The band between is where fluid typography breaks.
- ❌
line-height: 1.5remon a fluid size — the ratio inverts as the size grows.
10. Source citations
- Brown, Flexible Typesetting — primary source. Designing systems rather than individual screens; typographic relationships across viewport sizes; responsive line length; measure as a visual decision; pressure and relief between size, spacing, and available space.
- Rutter, Web Typography — em/rem/ch units; responsive typography; why
chvaries by font and is unreliable for layout. - Lupton (ed.), Type on Screen — mobile and responsive composition; dynamic rather than fixed compositions.
- Latin, Better Web Typography — responsive web typography; revisiting line-height when measure changes.
- WCAG 2.2 §1.4.4 (resize text to 200%).
- MDN —
clamp(), container queries,text-wrap.