Skip to content

Font Size

Chris Wachtman edited this page Feb 13, 2025 · 4 revisions

Font Sizes on USA.gov should be managed using USWDS Design Tokens as much as possible. Using design tokens limits our font sizes to a handful of options which helps with consistency and establishes a stronger sense of hierarchy.

This guide mirrors our existing guide, How to Use USWDS Design Tokens, and how it relates to setting font sizes.

4 Ways to Use Font Size Tokens

Utility Class

font-size-[family]-[size] - Sets the font size to medium

font-[family]-[size] - Sets the font family to serif and font size to medium

Set a font size in HTML by using a class that specifies the font family and size.

Simple way to set a font-size without changing CSS.

<div class="font-size-serif-md">
  Sets the font size to medium
</div>

<div class="font-serif-md">
  Sets the font family to serif and font size to medium
</div>

Why is it necessary to specify [family] even when only setting the font-size?

See Font Size Normalization


Theme Variable

Modify the default font sizes of base elements by adding these to _uswds-theme.scss which is processed before the design system is compiled.

Powerful option for making sweeping, site-wide font size changes.

$theme-body-font-size: "md",
$theme-h1-font-size: "xl",
$theme-h2-font-size: "lg",
$theme-h3-font-size: "md",

List of available USWDS Theme Variables


Utility Mixin

u-font-size([family], [size]) - Sets the font size to medium

u-font([family], [size]) - Sets the font family to serif and font size to medium

Set a font size in SCSS by using a mixin that specifies the font family and size.

Both of the mixins require specifying the font family as well as the font size token.

.example1 {
  @include u-font-size('sans', 'md');
}

.example2 {
  @include u-font('sans', 'md');
}

Why is it necessary to specify [family] even when only setting the font-size?

See Font Size Normalization


Token Function

size([family], [size]); - Sets the font font size to medium

The token function for font-size is just called “size” (I personally believe it should be “font-size”…)

.example {
  font-size: size('sans', 'md');
}

Why is it necessary to specify [family] even when only setting the font-size?

See Font Size Normalization

Notice that since the function returns a value rather than a full set of CSS rules, it can only be used for the font size property even though is still requires a font family to be defined. There is a function for font-family (called “family” although I think it should be called “font-family”). I chose to use mixins rather than functions for our font sizes because replicating the u-font mixin using functions would be more repetitive.

These 3 styles are all equivalent:

.mixin {
  @include u-font('sans', 'md');
}

.function {
  font-family: family('sans');
  font-size: size('sans', 'md');
}

.compiled-css {
	font-family: Source Sans Pro Web,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;
	font-size: 1.13rem;
}

Font Size Normalization

USWDS normalizes font sizes differently depending on which font family is used.

https://designsystem.digital.gov/design-tokens/typesetting/overview/#normalization-2

The serif font (Merriweather) is normalized to 98%

The sans font (Source Sans Pro) is normalized to 106%

The chart below shows font sizes & families we use on USA.gov. The blank spaces are size/family combinations that we are not using.

Notice that for a given token, the serif font will have a rem size that results in a px size slightly below the optical size, where as the sans font is similarly shifted to be slightly larger than the optical size.

Token Optical px Serif px Serif rem Sans px Sans rem
'3xs' 13px
'2xs' 14px 14.88px .93rem
'xs' 15px 16px 1rem
'sm' 16px 16.96px 1.06rem
'md' 17px 16.64px 1.04rem 18.08px 1.13rem
'lg' 22px 21.44px 1.46rem 23.36px 1.34rem
'xl' 32px 31.2px 1.95rem 34.08px 2.13rem
'2xl' 40px 39.04px 2.44rem 42.56px 2.66rem
'3xl' 48px

Advantage of Using Design Tokens

Before consolidating our font sizes using design tokens, we had an overwhelming variety of font sizes being used across the site. Font size were typically tweak by picking whatever number seemed to look OK and the units often varied too. Using design tokens limits our font sizes to a handful of options which helps with consistency and establishes a stronger sense of hierarchy.

When to Not Use Design Tokens

One place that we are not using a design token for a font size is the pipe separator character between the phone number and the search box in the header on desktop.

To make that character match the height of the search box, it is set to a font-size of 2rem (32px).

Using a design token here would not be able to achieve the same precision alignment.

I do believe that separator could be more reliably sized using border styles or simply be removed all together.