Design Systems

Typography ที่ตอบสนองในระบบการออกแบบ

Updated กุมภาพันธ์ 24, 2026
การปรับขนาดการพิมพ์ในทุก breakpoints — type scales แบบตอบสนอง, fluid sizing ด้วย clamp() และการรักษาลำดับชั้นจากมือถือถึงเดสก์ท็อป

Responsive Typography in Design Systems

Typography that works well at 1440px and looks broken at 375px is one of the most common quality issues in design system implementations. A 48px display heading looks commanding on a widescreen monitor; on a phone, it may consume four lines and push the rest of the content below the fold. A comfortable body text line length at desktop becomes a cramped single-word-per-line column on mobile if the font isn't scaled thoughtfully.

The challenge in a design system context is not solving responsive typography for a single page — it is solving it once, systematically, in a way that every product and every component that consumes the system inherits automatically.


The Responsive Typography Challenge

Responsive typography is harder than responsive layout because it has more dimensions. Layout is primarily two-dimensional: a grid column becomes full-width on mobile, a sidebar stacks below content. Typography involves size, leading, tracking, measure (line length), weight, and the relationships between hierarchy levels — all of which interact differently at different viewport sizes.

The specific problems that arise without a responsive type system:

Display text overflow. Large headings that look fine at 1200px break layouts on narrow viewports. A font-size: 3.5rem heading at a single breakpoint forces every product team to override it for mobile on their own.

Broken hierarchy. A type scale with a 1.333 ratio (Perfect Fourth) creates clear visual hierarchy at desktop. On mobile, the same scale may make the difference between heading levels too subtle — or if the scale is too tight, the heading may look indistinguishable from emphasized body text.

Line length problems. Optimal reading measure is 55–75 characters per line. On a 375px viewport with 16px body text, this is achievable. But if the type system increases body size to 18px on mobile (a well-intentioned accessibility move), the line length drops below comfortable reading range unless the layout also adjusts.

Spacing mismatches. If font sizes scale down on mobile but the vertical spacing between headings and body paragraphs does not, the proportional relationships break. Responsive typography must include responsive spacing.

Design systems like Shopify Polaris and IBM Carbon address this by defining separate type specifications for different viewport contexts, not just a single set of values with occasional overrides.


Breakpoint-Based vs. Fluid Approaches

Two primary strategies exist for responsive typography: breakpoint-based switching and fluid (continuous) scaling. Both have legitimate use cases, and the best systems often combine them.

Breakpoint-Based Scaling

In this approach, you define separate token values for different viewport ranges and switch between them at defined breakpoints.

/* Default (mobile-first): smaller scale */
:root {
  --font-size-display:    2.25rem;  /* 36px */
  --font-size-heading-lg: 1.75rem;  /* 28px */
  --font-size-heading-md: 1.375rem; /* 22px */
  --font-size-heading-sm: 1.125rem; /* 18px */
  --font-size-body:       1rem;     /* 16px */
}

/* Tablet and above: medium scale */
@media (min-width: 768px) {
  :root {
    --font-size-display:    3rem;    /* 48px */
    --font-size-heading-lg: 2.25rem; /* 36px */
    --font-size-heading-md: 1.75rem; /* 28px */
    --font-size-heading-sm: 1.375rem;/* 22px */
    --font-size-body:       1rem;    /* 16px */
  }
}

/* Desktop: full scale */
@media (min-width: 1200px) {
  :root {
    --font-size-display:    3.815rem; /* 61px */
    --font-size-heading-lg: 2.441rem; /* 39px */
    --font-size-heading-md: 1.953rem; /* 31.25px */
    --font-size-heading-sm: 1.5625rem;/* 25px */
    --font-size-body:       1rem;     /* 16px — body stays fixed */
  }
}

Because components reference var(--font-size-display) rather than a hard-coded value, every component in the library automatically picks up the appropriate size for the current viewport. The system-level change propagates everywhere.

Advantages: Simple to reason about, easy to test (check at each breakpoint), predictable output, works in all browsers.

Disadvantages: Abrupt jumps at breakpoints can feel mechanical. The values at a 769px viewport (just past the 768px breakpoint) may look disproportionately large compared to 767px.

Fluid Scaling with clamp()

CSS clamp(minimum, preferred, maximum) allows values that scale smoothly between a minimum and a maximum based on viewport width.

:root {
  --font-size-display:    clamp(2.25rem, 5vw + 1rem, 3.815rem);
  --font-size-heading-lg: clamp(1.75rem, 3.5vw + 0.75rem, 2.441rem);
  --font-size-heading-md: clamp(1.375rem, 2.5vw + 0.5rem, 1.953rem);
  --font-size-heading-sm: clamp(1.125rem, 1.5vw + 0.5rem, 1.5625rem);
  --font-size-body:       1rem; /* body stays fixed */
}

The preferred value (5vw + 1rem) is a linear interpolation. As viewport width grows, the vw component increases proportionally. The clamp() function ensures the value never drops below the minimum or exceeds the maximum.

Calculating fluid values precisely: The linear interpolation between two known points can be calculated with:

preferred = (max-value - min-value) / (max-viewport - min-viewport) * 100vw + (min-value - min-viewport * slope)

A fluid typography calculator automates this arithmetic. For a heading that should be 28px at 375px viewport and 39px at 1200px:

slope = (39 - 28) / (1200 - 375) = 11 / 825 ≈ 0.01333
intercept = 28 - (375 × 0.01333) ≈ 23px ≈ 1.4375rem
preferred = 1.333vw + 1.4375rem
clamp = clamp(1.75rem, 1.333vw + 1.4375rem, 2.441rem)

Advantages: Smooth, continuous scaling with no jarring jumps. Adapts to every viewport width rather than just the defined breakpoints.

Disadvantages: Harder to reason about, harder to test (you need to test across a range, not just at discrete breakpoints), and the math is non-trivial to write by hand. Browser DevTools responsive mode helps, but thorough fluid typography testing requires checking multiple viewport widths.


Scaling the Type Scale Across Viewports

When designing the responsive behavior of a type scale, think in terms of scale shifts rather than individual token adjustments.

A practical mental model: at mobile, the display sizes are suppressed by one or two steps, and the heading sizes behave like display sizes. The scale effectively "contracts" — the same number of steps is available, but they span a smaller range of sizes.

Step Desktop Tablet Mobile
Display 61px 48px 36px
Heading LG 39px 36px 28px
Heading MD 31.25px 28px 22px
Heading SM 25px 22px 18px
Body LG 20px 18px 18px
Body 16px 16px 16px
Caption 12.8px 12.8px 12.8px

Notice that body, body-lg, and caption are relatively stable across viewports. The most dramatic scaling happens at the larger end of the scale. This pattern is intentional: body text is calibrated for comfortable reading and does not need to change, while display and heading text must adapt to available viewport width.

Also notice that the relationship between steps contracts on mobile. At desktop, Heading SM is 25px and Body is 16px — a ratio of 1.5625. At mobile, Heading SM is 18px and Body is 16px — a ratio of only 1.125. On mobile, you must maintain hierarchy through other means: weight, spacing, color, and capitalization, not size alone. This is an important design system decision that should be documented explicitly.

/* Example: maintaining heading hierarchy on mobile through weight */
@media (max-width: 767px) {
  .heading-sm {
    font-size: var(--font-size-heading-sm); /* 18px on mobile */
    font-weight: 700; /* heavier weight compensates for smaller size difference */
    letter-spacing: -0.01em;
  }

  .body-lg {
    font-size: var(--font-size-body); /* drops to body size on mobile */
    font-weight: 500; /* medium weight distinguishes from regular body */
  }
}

Maintaining Hierarchy on Small Screens

Small screens compress the visual space available for typographic hierarchy. Three techniques help maintain clear hierarchy when size alone cannot do the job:

Weight as hierarchy

On mobile, increase the weight of headings relative to body text. If body text is Regular (400) and headings are Semibold (600) on desktop, consider making headings Bold (700) on mobile. The extra weight creates visual differentiation even when the size difference is smaller.

Inter's weight range (100–900) makes this practical. Roboto and Source Sans Pro similarly offer enough weights to work with this approach.

@media (max-width: 767px) {
  .section-heading {
    font-weight: var(--font-weight-bold); /* 700 on mobile */
  }
}

@media (min-width: 768px) {
  .section-heading {
    font-weight: var(--font-weight-semibold); /* 600 on desktop */
  }
}

Spacing as separator

Generous vertical space above headings signals a new section even when the heading itself is not dramatically larger than the body text. A margin-top: 2rem above a mobile heading reads as clearly as a much larger heading on desktop, because the white space creates the visual break.

Ensure your spacing tokens scale with your typography tokens. If heading sizes change at breakpoints, the spacing above and below them should change proportionally.

Color and contrast

A muted color for body text and a higher-contrast color for headings creates hierarchy independently of size. This works well for subheadings and labels, where size-based differentiation may be minimal on mobile.

Reduce the number of heading levels

Consider whether your mobile typography needs the same number of distinct heading levels as desktop. A desktop layout with H1, H2, H3, and H4 in clear visual sequence may legitimately collapse to H1, H2, and H3 on mobile — with H3 and H4 treated as semantically equivalent visually. Document this as an explicit design system decision, not an oversight.


Implementation Patterns

Several implementation patterns have proven reliable for production design systems.

Define all responsive behavior in the token layer. Components reference only semantic tokens. This is the cleanest separation of concerns: responsive rules live in one file, component rules live in component files, and they never mix.

/* tokens.css — all responsive type rules live here */
:root {
  --font-size-display: clamp(2.25rem, 5vw + 1rem, 3.815rem);
  --font-size-heading-lg: clamp(1.75rem, 3.5vw + 0.75rem, 2.441rem);
  --font-size-body: 1rem;
  --font-weight-heading: 600;
}

@media (max-width: 767px) {
  :root {
    --font-weight-heading: 700; /* heavier on mobile */
  }
}

/* button.css — only semantic token references, no breakpoints */
.button {
  font-size: var(--font-size-label);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-tight);
}

Pattern 2: Utility classes

Some systems expose responsive typography as utility classes, similar to how Tailwind CSS handles it. This gives product teams explicit control without requiring them to write new CSS.

.text-display      { font-size: var(--font-size-display); }
.text-heading-lg   { font-size: var(--font-size-heading-lg); }
.text-heading-md   { font-size: var(--font-size-heading-md); }
.text-body         { font-size: var(--font-size-body); }

/* Responsive overrides */
@media (max-width: 767px) {
  .sm\:text-heading-lg { font-size: var(--font-size-heading-lg); }
  .sm\:text-heading-md { font-size: var(--font-size-heading-md); }
}

Pattern 3: Component-level media queries

For components with highly specific responsive needs — a hero component that has dramatically different layout and typography at each viewport — component-level media queries may be more appropriate. Use this as the exception, not the rule.

/* hero.css */
.hero-title {
  font-size: var(--font-size-heading-md);
  font-weight: var(--font-weight-bold);
}

@media (min-width: 768px) {
  .hero-title {
    font-size: var(--font-size-display-sm);
    font-weight: var(--font-weight-semibold);
  }
}

@media (min-width: 1200px) {
  .hero-title {
    font-size: var(--font-size-display);
    font-weight: var(--font-weight-semibold);
  }
}

Testing responsive type at scale

Automated visual regression testing with tools like Chromatic or Percy catches unintended changes when tokens are updated. Set up visual snapshots at three viewport widths (375px, 768px, 1280px minimum) for every component in your library that contains text. When a token value changes, the diff will immediately show whether the change propagated correctly or created unexpected side effects.

The fluid typography calculator is useful during design to preview how clamp values will behave across the viewport range before committing to specific numbers.

Responsive typography is not a feature you add to a design system — it is a property the system must have from day one. Retrofit it later, and you will face a migration that touches every component and every page that consumes them.

Type Scale Systems

Typography Terms

Try These Tools

Fonts Mentioned

Related Articles