BlogPlaygroundOne

Typography Migration Guide

This page describes changes introduced in v4.0.0 and maps the legacy typography variants to the new Material Design 3 (MD3) variants.

Quick Reference

MD2 (Legacy)MD3 (New)
h1 - h3display-large, display-medium, display-small
h4 - h6headline-large, headline-medium, headline-small
subtitle-1, body-1body-large
body-2body-medium
captionbody-small
button, subtitle-2label-large
overlinelabel-small
display large.text-display-large
Size3.5625rem
Line height1.1228070175
Weight400
Letter spacing-.0043859649em
display medium.text-display-medium
Size2.8125rem
Line height1.1555555556
Weight400
Letter spacingnormal
display small.text-display-small
Size2.25rem
Line height1.2222222222
Weight400
Letter spacingnormal
headline large.text-headline-large
Size2rem
Line height1.25
Weight400
Letter spacingnormal
headline medium.text-headline-medium
Size1.75rem
Line height1.2857142857
Weight400
Letter spacingnormal
headline small.text-headline-small
Size1.5rem
Line height1.3333333333
Weight400
Letter spacingnormal
title large.text-title-large
Size1.375rem
Line height1.2727272727
Weight400
Letter spacingnormal
title medium.text-title-medium
Size1rem
Line height1.5
Weight500
Letter spacing.009375em
title small.text-title-small
Size.875rem
Line height1.4285714286
Weight500
Letter spacing.0071428571em
body large.text-body-large
Size1rem
Line height1.5
Weight400
Letter spacing.03125em
body medium.text-body-medium
Size.875rem
Line height1.4285714286
Weight400
Letter spacing.0178571429em
body small.text-body-small
Size.75rem
Line height1.3333333333
Weight400
Letter spacing.0333333333em
label large.text-label-large
Size.875rem
Line height1.4285714286
Weight500
Letter spacing.0071428571em
label medium.text-label-medium
Size.75rem
Line height1.3333333333
Weight500
Letter spacing.0416666667em
label small.text-label-small
Size.6875rem
Line height1.4545454545
Weight500
Letter spacing.0454545455em

Conservative Migration Mapping

If you want to keep text sizes as close as possible to the previous MD2 sizes, use this mapping table:

Legacy MD2 ClassMD2 SizeRecommended MD3 ClassMD3 SizeNotes
text-h196pxn/an/a⚠️ needs custom variant
text-h260pxtext-display-large57pxClose match
text-h348pxtext-display-medium45pxClose match
text-h434pxtext-headline-large32pxClose match
text-h524pxtext-headline-small24px✓ Exact match
text-h620pxtext-title-large22pxClose match
text-subtitle-116pxtext-body-large16px✓ Exact match
text-subtitle-214pxtext-title-small14px✓ Exact match (500 weight)
text-body-116pxtext-body-large16px✓ Exact match
text-body-214pxtext-body-medium14px✓ Exact match
text-button14pxtext-label-large14px✓ Exact match (no uppercase)
text-caption12pxtext-body-small12px✓ Exact match
text-overline12pxtext-label-medium12px⚠️ No uppercase, different letter spacing

Migration Steps

1. Update class names in HTML templates

Replace legacy class names with MD3 equivalents:

<!-- Before -->
<h1 class="text-h1">Title</h1>
<p class="text-body-1">Content</p>
<span class="text-caption">Small text</span>

<!-- After -->
<h1 class="text-display-large">Title</h1>
<p class="text-body-large">Content</p>
<span class="text-body-small">Small text</span>

2. Sass customization

If your app has some customization applied to $typography, it needs to be re-mapped to new variants.

src/settings.scss
// Before
use 'vuetify/settings' with (
  $typography: (
    'h1': (// <- only adds `text-h1` as a new class next to MD3 variants
      'size': 3rem,
      'weight': 400,
    ),
  ),
)
src/settings.scss
// After
use 'vuetify/settings' with (
  $typography: (
    'display-large': (// <- migrated to semantic equivalent
      'size': 3rem,
      'weight': 400, // <- can be skipped, same as default
    ),
  ),
)

Detached Sass variables

New typography configuration does not cover text-transform. So some of the Sass variables are now detached from typography and default to none.

Sass VariableLegacy value
$button-text-transformsettings.$typography » button » text-transform
$card-text-text-transformsettings.$typography » body-2 » text-transform
$system-bar-text-transformsettings.$typography » caption » text-transform

In order to restore the customized values, pass them directly to the specific variables:

src/settings.scss
@use 'vuetify/settings' with (
  $button-text-transform: uppercase,
  $card-text-text-transform: none,
  $system-bar-text-transform: none,
);

Breaking Changes

  1. Class names: All default typography classes changed to align with Material Design 3
  2. No text-transform by default: The overlinelabel-small is not an equivalent replacement as it looses uppercase, letter spacing is 3x smaller, etc.
  3. Different sizing: MD3 variants follow Material Design 3 specifications which differ from MD2

Restoring MD2 typography

If you want to avoid visual regression entirely, you can restore MD2 typography using configuration snippets bellow.

src/typography.scss
$body-font-family: 'Roboto', sans-serif;
$heading-font-family: $body-font-family;

$typography: (
  (
    'h1': (
      'size': 6rem,
      'weight': 300,
      'line-height': 1,
      'letter-spacing': -.015625em,
      'font-family': $heading-font-family,
      'text-transform': none
    ),
    'h2': (
      'size': 3.75rem,
      'weight': 300,
      'line-height': 1,
      'letter-spacing': -.0083333333em,
      'font-family': $heading-font-family,
      'text-transform': none
    ),
    'h3': (
      'size': 3rem,
      'weight': 400,
      'line-height': 1.05,
      'letter-spacing': normal,
      'font-family': $heading-font-family,
      'text-transform': none
    ),
    'h4': (
      'size': 2.125rem,
      'weight': 400,
      'line-height': 1.175,
      'letter-spacing': .0073529412em,
      'font-family': $heading-font-family,
      'text-transform': none
    ),
    'h5': (
      'size': 1.5rem,
      'weight': 400,
      'line-height': 1.333,
      'letter-spacing': normal,
      'font-family': $heading-font-family,
      'text-transform': none
    ),
    'h6': (
      'size': 1.25rem,
      'weight': 500,
      'line-height': 1.6,
      'letter-spacing': .0125em,
      'font-family': $heading-font-family,
      'text-transform': none
    ),
    'subtitle-1': (
      'size': 1rem,
      'weight': normal,
      'line-height': 1.75,
      'letter-spacing': .009375em,
      'font-family': $body-font-family,
      'text-transform': none
    ),
    'subtitle-2': (
      'size': .875rem,
      'weight': 500,
      'line-height': 1.6,
      'letter-spacing': .0071428571em,
      'font-family': $body-font-family,
      'text-transform': none
    ),
    'body-1': (
      'size': 1rem,
      'weight': 400,
      'line-height': 1.5,
      'letter-spacing': .03125em,
      'font-family': $body-font-family,
      'text-transform': none
    ),
    'body-2': (
      'size': .875rem,
      'weight': 400,
      'line-height': 1.425,
      'letter-spacing': .0178571429em,
      'font-family': $body-font-family,
      'text-transform': none
    ),
    'button': (
      'size': .875rem,
      'weight': 500,
      'line-height': 2.6,
      'letter-spacing': .0892857143em,
      'font-family': $body-font-family,
      'text-transform': uppercase
    ),
    'caption': (
      'size': .75rem,
      'weight': 400,
      'line-height': 1.667,
      'letter-spacing': .0333333333em,
      'font-family': $body-font-family,
      'text-transform': none
    ),
    'overline': (
      'size': .75rem,
      'weight': 500,
      'line-height': 2.667,
      'letter-spacing': .1666666667em,
      'font-family': $body-font-family,
      'text-transform': uppercase
    )
  ),
  $typography
);

$flat-typography: ();
@each $type, $values in $typography {
  $flat-typography: map-deep-merge(
    $flat-typography,
    (#{$type}: (
      map.get($values, 'size'),
      map.get($values, 'weight'),
      map.get($values, 'line-height'),
      map.get($values, 'letter-spacing'),
      map.get($values, 'font-family'),
      map.get($values, 'text-transform'),
    ))
  );
}
src/settings.scss
@use './typography' as *;
@use 'vuetify/settings' with (
  $utilities: (
    "typography": (
      property: (
        font-size,
        font-weight,
        line-height,
        letter-spacing,
        font-family,
        text-transform // <-- restoring this line
      ),
      values: $flat-typography, // <-- ensures we only generate MD2 variants
    ),
  ),

  $alert-title-font-size: tools.map-deep-get(.$typography, 'h6', 'size'),
  $alert-title-font-weight: tools.map-deep-get(.$typography, 'h6', 'weight'),
  $alert-title-letter-spacing: tools.map-deep-get(.$typography, 'h6', 'letter-spacing'),
  $banner-font-size: tools.map-deep-get(.$typography, 'body-2', 'size'),
  $banner-line-height: tools.map-deep-get(.$typography, 'subtitle-2', 'line-height'),
  $breadcrumbs-item-icon-font-size: tools.map-deep-get(.$typography, 'body-1', 'size'),
  $breadcrumbs-line-height: tools.map-deep-get(.$typography, 'subtitle-2', 'line-height'),
  $button-font-size: tools.map-deep-get(.$typography, 'button', 'size'),
  $button-font-weight: tools.map-deep-get(.$typography, 'button', 'weight'),
  $button-text-letter-spacing: tools.map-deep-get(.$typography, 'button', 'letter-spacing'),
  $button-text-transform: tools.map-deep-get(.$typography, 'button', 'text-transform'),
  $card-title-font-size: tools.map-deep-get(.$typography, 'h6', 'size'),
  $card-title-font-weight: tools.map-deep-get(.$typography, 'h6', 'weight'),
  $card-title-letter-spacing: tools.map-deep-get(.$typography, 'h6', 'letter-spacing'),
  $card-title-line-height: tools.map-deep-get(.$typography, 'h6', 'line-height'),
  $card-subtitle-font-size: tools.map-deep-get(.$typography, 'body-2', 'size'),
  $card-subtitle-font-weight: tools.map-deep-get(.$typography, 'body-2', 'weight'),
  $card-subtitle-letter-spacing: tools.map-deep-get(.$typography, 'body-2', 'letter-spacing'),
  $card-subtitle-line-height: tools.map-deep-get(.$typography, 'body-2', 'line-height'),
  $card-text-font-size: tools.map-deep-get(.$typography, 'body-2', 'size'),
  $card-text-font-weight: tools.map-deep-get(.$typography, 'body-2', 'weight'),
  $card-text-letter-spacing: tools.map-deep-get(.$typography, 'body-2', 'letter-spacing'),
  $card-text-line-height: tools.map-deep-get(.$typography, 'body-2', 'line-height'),
  $card-text-text-transform: tools.map-deep-get(.$typography, 'body-2', 'text-transform'),
  $chip-font-size: tools.map-deep-get(.$typography, "button", "size"),
  $dialog-card-text-letter-spacing: tools.map-deep-get(.$typography, 'body-1', 'letter-spacing'),
  $empty-state-headline-font-size: functions.map-deep-get(.$typography, 'h2', 'size'),
  $empty-state-headline-font-weight: functions.map-deep-get(.$typography, 'h2', 'weight'),
  $empty-state-headline-line-height: functions.map-deep-get(.$typography, 'h2', 'line-height'),
  $empty-state-headline-mobile-font-size: functions.map-deep-get(.$typography, 'h4', 'size'),
  $empty-state-text-font-size: functions.map-deep-get(.$typography, 'body-2', 'size'),
  $empty-state-text-font-weight: functions.map-deep-get(.$typography, 'body-2', 'weight'),
  $empty-state-text-line-height: functions.map-deep-get(.$typography, 'body-2', 'line-height'),
  $empty-state-title-font-size: functions.map-deep-get(.$typography, 'h6', 'size'),
  $empty-state-title-font-weight: functions.map-deep-get(.$typography, 'h6', 'weight'),
  $empty-state-title-line-height: functions.map-deep-get(.$typography, 'h6', 'line-height'),
  $fab-font-size: tools.map-deep-get(.$typography, 'button', 'size'),
  $fab-font-weight: tools.map-deep-get(.$typography, 'button', 'weight'),
  $input-font-size: tools.map-deep-get(.$typography, 'body-1', 'size'),
  $input-font-weight: tools.map-deep-get(.$typography, 'body-1', 'weight'),
  $list-item-nav-subtitle-font-weight: tools.map-deep-get(.$typography, 'body-2', 'weight'),
  $list-item-nav-subtitle-letter-spacing: tools.map-deep-get(.$typography, 'body-2', 'letter-spacing'),
  $list-item-subtitle-font-size: tools.map-deep-get(.$typography, 'body-2', 'size'),
  $list-item-subtitle-font-weight: tools.map-deep-get(.$typography, 'body-2', 'weight'),
  $list-item-subtitle-letter-spacing: tools.map-deep-get(.$typography, 'body-2', 'letter-spacing'),
  $list-item-title-font-size: tools.map-deep-get(.$typography, 'body-1', 'size'),
  $list-item-title-font-weight: tools.map-deep-get(.$typography, 'body-1', 'weight'),
  $list-item-title-letter-spacing: tools.map-deep-get(.$typography, 'subtitle-1', 'letter-spacing'),
  $list-item-title-line-height: tools.map-deep-get(.$typography, 'body-1', 'line-height'),
  $slider-thumb-label-font-size: tools.map-deep-get(.$typography, 'caption', 'size'),
  $snackbar-font-size: tools.map-deep-get(.$typography, 'body-2', 'size'),
  $snackbar-font-weight: tools.map-deep-get(.$typography, 'body-2', 'weight'),
  $snackbar-letter-spacing: tools.map-deep-get(.$typography, 'body-2', 'letter-spacing'),
  $snackbar-line-height: tools.map-deep-get(.$typography, 'body-2', 'line-height'),
  $system-bar-font-size: tools.map-deep-get(.$typography, 'caption', 'size'),
  $system-bar-font-weight: tools.map-deep-get(.$typography, 'caption', 'weight'),
  $system-bar-letter-spacing: tools.map-deep-get(.$typography, 'caption', 'letter-spacing'),
  $system-bar-line-height: tools.map-deep-get(.$typography, 'caption', 'line-height'),
  $system-bar-text-transform: tools.map-deep-get(.$typography, 'caption', 'text-transform'),
  $table-header-font-size: tools.map-deep-get(.$typography, 'caption', 'size'),
  $table-font-size: tools.map-deep-get(.$typography, 'body-2', 'size'),
  $table-row-font-size: tools.map-deep-get(.$typography, 'subtitle-2', 'size'),
  $icon-btn-font-size: tools.map-deep-get(.$typography, 'button', 'size'),
  $icon-btn-font-weight: tools.map-deep-get(.$typography, 'button', 'weight'),
);

Ready for more?

Continue your learning with related content selected by the Team or move between pages by using the navigation links below.