The typography scale is one of those decisions that looks small at concept time and becomes structural by launch. I have carried a type scale into Shopify four times in the last two years, and the version I keep coming back to is six steps, three families, and two clamp expressions for the mobile hero. Anything more is a type system pretending to be architecture. Anything less breaks when the PDP hero meets a long product name on mobile.
These are the field notes from the last three Shopify builds.
- --t-display4.5remShip the loop
- --t-h13remWhy this matters
- --t-h22remA sub-section
- --t-h31.375remA minor head
- --t-body1remParagraph copy reads here.
- --t-small0.8125remFootnote / meta
2026-02-10: the scale in Figma
Six text styles in Figma: display, h1, h2, h3, body, small. The first two are DM Serif Display (or whatever display face the brand lands on). The middle two are DM Sans semibold. The last two are DM Sans regular. A mono style sits alongside for code, tabular data, and eyebrow labels. That is seven styles total including the mono; seven is a number a designer can hold in working memory without opening the style panel.
The ratios are not on a geometric scale. I tried a 1.25 modular scale on one project and abandoned it. The intermediate sizes (25px, 31px) did not earn their existence on real pages. I went back to a hand-tuned scale where each step has a purpose: 72 for display, 48 for page h1, 32 for section h2, 22 for subhead, 16 for body, 13 for captions.
Each style is named by role, not appearance. "Display" not "72 / Serif / Bold." When the brand shifts and the display face changes from DM Serif to Playfair, the style update is local. Every Figma frame that used "Display" updates automatically.
2026-02-14: the translation to Liquid
Shopify themes do not have a native design token system. The theme I ship translates Figma styles to CSS custom properties declared in theme.liquid and consumed by section-level Liquid snippets and CSS classes.
The scale lives in one CSS block:
:root {
--t-display: clamp(2.5rem, 7vw, 7.5rem);
--t-h1: clamp(2rem, 5vw, 3.5rem);
--t-h2: clamp(1.5rem, 3vw, 2rem);
--t-h3: 1.375rem;
--t-body: 1rem;
--t-small: 0.8125rem;
--lh-display: 0.88;
--lh-h1: 0.92;
--lh-h2: 1.1;
--lh-body: 1.5;
}
The sections (hero, pdp-price-block, collection-tile, product-card) reference --t-display, --t-h1, etc. via utility classes. No section hard-codes a font size.
The clamp on the top two is what keeps the mobile hero from wrapping catastrophically. At 320 pixels wide, 7.5rem would force the hero to wrap into five lines on most product names. The clamp brings it down to about 2.5rem on that viewport, which wraps into two lines gracefully.
2026-02-18: the line-height decision
Line-heights are part of the scale, not an afterthought. The rule I use: the larger the type, the tighter the line-height. Display at 0.88. H1 at 0.92. H2 at 1.1. Body at 1.5.
The tight line-heights on display and h1 are why mobile type looks aggressive and readable instead of sloppy. A display at line-height 1.2 looks like a page mockup; a display at 0.88 looks like a brand. Rachel Andrew calls this the "hero h1 is sacred" rule and I have never found a reason to deviate from it on a DTC build.
Body line-height at 1.5 is standard. A touch higher (1.55) works if the body font is a narrower sans. Lower than 1.5 reads as cramped even on desktop.
On mobile, the clamped display compresses so the 0.88 line-height still looks right at the smaller rendered size. The clamp does not need a separate mobile line-height; the ratio holds.
2026-02-22: the Shopify section handoff
The way the scale actually lands in a theme is through Liquid section code plus CSS. A hero section declares:
<h1 class="hero-display">{{ section.settings.heading }}</h1>
And the CSS:
.hero-display {
font-family: var(--font-serif-display);
font-size: var(--t-display);
line-height: var(--lh-display);
color: var(--ink);
}
Every heading element in every section follows this pattern. The section never inlines a size. The designer working in Figma and the engineer working in the theme both reference the same six named styles.
The test is whether a merchandiser who does not know CSS can ship a new landing page in the theme editor without breaking typography. If the section settings are parameterized correctly (heading size picks from a short list of style names, not raw pixel values) the merchandiser can only pick valid combinations. Type stays on-brand by construction.
2026-03-02: what breaks without the scale
I inherited a Shopify theme last quarter that had no type scale. Every section inlined its own font sizes. Nine different h1 sizes across the site. Twenty-three different body sizes. Three different body fonts because three different developers had shipped different sections at different times.
The fix took two weeks:
First, I catalogued every size and font in the theme by grepping for font-size and font-family. 142 instances.
Second, I mapped them to the six-step scale. Most of the 142 inlined sizes collapsed into one of the six steps with a small rounding tolerance (20px and 22px both became the h3 step; 14px, 15px, and 16px all became body). About 20 instances were genuinely outside the scale and had to be ticketed for design review.
Third, I refactored the 142 instances to use the CSS custom properties. Each section went from inlined styles to utility classes. The diff was large (four thousand lines changed) but the cognitive load dropped dramatically. Adding a new section now picks from six type styles instead of picking a size at random.
“A type scale is the difference between a theme a merchandiser can safely modify and a theme that requires a developer on every page edit. The gap compounds every launch.
”
2026-03-10: the mobile test
The test I run on every scale change is viewing the homepage, PDP, and collection on an iPhone 12 Mini (390 wide) and a Galaxy S8 (360 wide) via the Playwright MCP in a local dev server. Not the Chrome devtools emulator. A real browser at the real viewport.
The hero h1 must wrap gracefully (two lines max) on the longest typical product name or campaign headline. The PDP title must not truncate. The collection tile titles must be legible at two-line wrap without clipping.
If any of those fail, the scale has a gap, usually in the clamp expression or the line-height. The fix is a one-line CSS change. The discipline is running the mobile check before declaring the theme shipped.
Serial surfaces: email and print
The scale transfers to email and print with slight adaptations.
Email clients are finicky about font sizing. The six-step scale simplifies to four in email because display and h1 collapse (mail clients do not do clamp, and the viewport range is narrower). I use inline styles in email with fixed sizes: 28px for hero, 22px for h2, 16px for body, 13px for footer. The naming still references the token roles; the values are just fixed.
Print is easier. Fixed sizes in a PDF generator (I use Reportlab for branded PDFs). The six steps translate to points: 54pt, 36pt, 24pt, 16pt, 12pt, 10pt. The aesthetic carries because the proportions are the same; only the rendering engine changes.
Running one scale across web, email, and print is the reason the brand feels like one brand instead of three brands that vaguely know each other. I shipped this architecture on the brand asset hub engagement I worked on (see the brand asset hub case) and it held for the full year of active use.
Frequently asked questions
Should I use a modular scale ratio like 1.25 or 1.333?
Try it and see. On small systems (under 6 steps) I have found hand-tuned scales outperform modular ratios because the intermediate sizes rarely appear on real pages. On larger systems (10+ steps) the modular ratio earns its keep as documentation. For DTC Shopify, six steps hand-tuned is enough.
How does this scale interact with Shopify's theme editor?
The theme editor can surface the six named styles as a dropdown in section settings. A merchandiser picks "H1" or "H2" from the dropdown; the section renders with the correct CSS class. This keeps the theme editor productive without letting anyone pick arbitrary sizes.
What about rich text blocks where the merchandiser writes inline HTML?
Rich text blocks should render with a scoped set of the type scale. I define a .rich-text class with body, h2, h3, and small available. The merchandiser cannot inline font sizes; the markdown-to-HTML converter renders tags which pick up the scoped styles. If they want a page-level hero, they use a hero section, not a rich text block.
Is this approach compatible with Tailwind?
Yes. Define the CSS custom properties in globals.css and reference them from the Tailwind theme via theme.extend.fontSize. Tailwind utilities and raw CSS both read the same token values. See also design tokens that survive a rebrand for the broader token pattern.
Can I use variable fonts to reduce the number of families?
Variable fonts simplify the shipping (one font file, multiple weights/widths) but do not change the scale conversation. The six-step scale is about font-size, line-height, and role, not about the font family. Variable fonts are a separate optimization that pairs well with the scale.
Sources and specifics
- Scale derived from four DTC Shopify builds across 2024-2026 and running on this site. The specific tight line-heights (0.88, 0.92) are tuned for DM Serif Display and DM Sans; other faces may need slightly different values.
- Typography sits inside the broader system covered in brand architecture for DTC and ties directly to the component handoff patterns in component library handoff when designer also codes.
- The inherited-theme refactor (142 inlined font-size instances collapsing to 6 scale steps) is from one specific engagement in Q1 2026; specific counts vary by theme but the shape of the cleanup is consistent.
- The mobile test discipline (Playwright MCP against 390 and 360 viewports) is project-wide policy on every Shopify and Next.js build I ship, including this site; see the project rules in the agent-ready shipping cadence article for the broader context.
- The email adaptation (fixed sizes, 4 effective steps) is from the email-lifecycle work documented in the Klaviyo lifecycle playbook.
- Full methodology is part of the Shopify theme starter.
