Typography
Apply token text styles (text-h1 to text-small, text-label, text-lead), typography colors and token font families.
On this page
Every text style in your tokens becomes one class that sets font family, size, weight, line height, letter spacing and text transform together. With the default tokens these are the headings text-h1 to text-h6, the content styles text-lead, text-body, text-small and text-label, and the component styles text-form-* and text-cookie-consent-*. Three color classes color text from the active theme.
Quick referenceLink to this section
| Class | Styles |
|---|---|
text-h1 | font-family: var(--font-h1-font-family);font-size: var(--typography-h1-font-size);font-weight: var(--font-h1-font-weight);letter-spacing: var(--typography-h1-letter-spacing);line-height: var(--typography-h1-line-height);text-transform: none;text-decoration: none;font-style: var(--font-h1-font-style); |
text-h2 | font-family: var(--font-h2-font-family);font-size: var(--typography-h2-font-size);font-weight: var(--font-h2-font-weight);letter-spacing: var(--typography-h2-letter-spacing);line-height: var(--typography-h2-line-height);text-transform: none;text-decoration: none;font-style: var(--font-h2-font-style); |
text-h3 | font-family: var(--font-h3-font-family);font-size: var(--typography-h3-font-size);font-weight: var(--font-h3-font-weight);letter-spacing: var(--typography-h3-letter-spacing);line-height: var(--typography-h3-line-height);text-transform: none;text-decoration: none;font-style: var(--font-h3-font-style); |
text-h4 | font-family: var(--font-h4-font-family);font-size: var(--typography-h4-font-size);font-weight: var(--font-h4-font-weight);letter-spacing: var(--typography-h4-letter-spacing);line-height: var(--typography-h4-line-height);text-transform: none;text-decoration: none;font-style: var(--font-h4-font-style); |
text-h5 | font-family: var(--font-h5-font-family);font-size: var(--typography-h5-font-size);font-weight: var(--font-h5-font-weight);letter-spacing: var(--typography-h5-letter-spacing);line-height: var(--typography-h5-line-height);text-transform: none;text-decoration: none;font-style: var(--font-h5-font-style); |
text-h6 | font-family: var(--font-h6-font-family);font-size: var(--typography-h6-font-size);font-weight: var(--font-h6-font-weight);letter-spacing: var(--typography-h6-letter-spacing);line-height: var(--typography-h6-line-height);text-transform: none;text-decoration: none;font-style: var(--font-h6-font-style); |
text-label | & { font-family: var(--font-label-font-family); font-size: var(--typography-label-font-size); font-weight: var(--font-label-font-weight); letter-spacing: var(--typography-label-letter-spacing); line-height: var(--typography-label-line-height); text-transform: uppercase; text-decoration: none; font-style: var(--font-label-font-style); }.post-card-label.text-label { color: color-mix(in srgb, currentColor 60%, transparent); }+ 1 more rule |
text-lead | font-family: var(--font-lead-font-family);font-size: var(--typography-lead-font-size);font-weight: var(--font-lead-font-weight);letter-spacing: var(--typography-lead-letter-spacing);line-height: var(--typography-lead-line-height);text-transform: none;text-decoration: none;font-style: var(--font-lead-font-style); |
text-body | font-family: var(--font-body-font-family);font-size: var(--typography-body-font-size);font-weight: var(--font-body-font-weight);letter-spacing: var(--typography-body-letter-spacing);line-height: var(--typography-body-line-height);text-transform: none;text-decoration: none;font-style: var(--font-body-font-style); |
text-small | font-family: var(--font-small-font-family);font-size: var(--typography-small-font-size);font-weight: var(--font-small-font-weight);letter-spacing: var(--typography-small-letter-spacing);line-height: var(--typography-small-line-height);text-transform: none;text-decoration: none;font-style: var(--font-small-font-style); |
text-form-label | font-family: var(--font-form-label-font-family);font-size: var(--typography-form-label-font-size);font-weight: var(--font-form-label-font-weight);letter-spacing: var(--typography-form-label-letter-spacing);line-height: var(--typography-form-label-line-height);text-transform: none;text-decoration: none;font-style: var(--font-form-label-font-style); |
text-form-description | font-family: var(--font-form-description-font-family);font-size: var(--typography-form-description-font-size);font-weight: var(--font-form-description-font-weight);letter-spacing: var(--typography-form-description-letter-spacing);line-height: var(--typography-form-description-line-height);text-transform: none;text-decoration: none;font-style: var(--font-form-description-font-style); |
text-form-block | font-family: var(--font-form-block-font-family);font-size: var(--typography-form-block-font-size);font-weight: var(--font-form-block-font-weight);letter-spacing: var(--typography-form-block-letter-spacing);line-height: var(--typography-form-block-line-height);text-transform: none;text-decoration: none;font-style: var(--font-form-block-font-style); |
text-form-inline | font-family: var(--font-form-inline-font-family);font-size: var(--typography-form-inline-font-size);font-weight: var(--font-form-inline-font-weight);letter-spacing: var(--typography-form-inline-letter-spacing);line-height: var(--typography-form-inline-line-height);text-transform: none;text-decoration: none;font-style: var(--font-form-inline-font-style); |
text-cookie-consent-title | font-family: var(--font-cookie-consent-title-font-family);font-size: var(--cookie-consent-title-font-size);font-weight: var(--font-cookie-consent-title-font-weight);letter-spacing: var(--cookie-consent-title-letter-spacing);line-height: var(--cookie-consent-title-line-height);text-transform: none;text-decoration: none;font-style: var(--font-cookie-consent-title-font-style); |
text-cookie-consent-description | font-family: var(--font-cookie-consent-description-font-family);font-size: var(--cookie-consent-description-font-size);font-weight: var(--font-cookie-consent-description-font-weight);letter-spacing: var(--cookie-consent-description-letter-spacing);line-height: var(--cookie-consent-description-line-height);text-transform: none;text-decoration: none;font-style: var(--font-cookie-consent-description-font-style); |
text-cookie-consent-category-title | font-family: var(--font-cookie-consent-category-title-font-family);font-size: var(--cookie-consent-category-title-font-size);font-weight: var(--font-cookie-consent-category-title-font-weight);letter-spacing: var(--cookie-consent-category-title-letter-spacing);line-height: var(--cookie-consent-category-title-line-height);text-transform: none;text-decoration: none;font-style: var(--font-cookie-consent-category-title-font-style); |
text-cookie-consent-button-primary | font-family: var(--font-cookie-consent-button-primary-font-family);font-size: var(--cookie-consent-button-primary-font-size);font-weight: var(--font-cookie-consent-button-primary-font-weight);letter-spacing: var(--cookie-consent-button-primary-letter-spacing);line-height: var(--cookie-consent-button-primary-line-height);text-transform: none;text-decoration: none;font-style: var(--font-cookie-consent-button-primary-font-style); |
text-cookie-consent-button-secondary | font-family: var(--font-cookie-consent-button-secondary-font-family);font-size: var(--cookie-consent-button-secondary-font-size);font-weight: var(--font-cookie-consent-button-secondary-font-weight);letter-spacing: var(--cookie-consent-button-secondary-letter-spacing);line-height: var(--cookie-consent-button-secondary-line-height);text-transform: none;text-decoration: none;font-style: var(--font-cookie-consent-button-secondary-font-style); |
color-label | color: var(--color-typography-label); |
color-heading | color: var(--color-typography-heading); |
color-body | color: var(--color-typography-body); |
Each font family in the font collection also becomes a font-<name> class:
| Class | Styles |
|---|---|
font-geist | font-family: Geist, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
Basic usageLink to this section
Add a text style class and a color class to an element. The heading styles pair with color-heading, the content styles with color-body, and text-label with color-label. Switch the preview between device widths: the sizes step up at md and lg.
const ramp = [
['text-h1', 'color-heading'],
['text-h2', 'color-heading'],
['text-h3', 'color-heading'],
['text-h4', 'color-heading'],
['text-h5', 'color-heading'],
['text-h6', 'color-heading'],
['text-lead', 'color-body'],
['text-body', 'color-body'],
['text-small', 'color-body'],
['text-label', 'color-label'],
]
export default function Demo() {
return (
<div className="flex w-full flex-col gap-4">
{ramp.map(([style, color]) => (
<div key={style} className="flex items-baseline gap-4">
<span className="color-label w-20 shrink-0 font-mono text-xs">{style}</span>
<div className={`${style} ${color} truncate`}>Systhema type ramp</div>
</div>
))}
</div>
)
}The Heading and Paragraph components apply the right pair for you: <Heading.h2> renders text-h2 color-heading, and <Paragraph type="lead"> renders text-lead color-body. Write the classes yourself when the element is not a heading or paragraph, or when the visual style should differ from the tag:
Rebuilding a catalogue in four weeks
export default function Demo() {
return (
<div className="flex max-w-[480px] flex-col gap-2">
<span className="text-label color-label">Case study</span>
<h2 className="text-h4 color-heading">Rebuilding a catalogue in four weeks</h2>
<div className="text-body color-body">
The document outline keeps its h2, the visual weight comes from the text-h4 style.
</div>
</div>
)
}text-label also sets text-transform: uppercase and a letter spacing from the tokens. The text-form-* styles are used by the form components and the text-cookie-consent-* styles by the cookie consent banner.
Text colorsLink to this section
color-heading, color-body and color-label read the typography roles of the color system, so they follow the theme of the nearest data-theme ancestor:
export default function Demo() {
return (
<div className="grid w-full grid-cols-2 gap-4">
{['default', 'dark'].map((theme) => (
<div key={theme} data-theme={theme} className="bg-layout-main flex flex-col gap-2 rounded-lg border border-(--color-foundations-surface-border) p-6">
<span className="text-label color-label">{theme}</span>
<span className="text-h5 color-heading">Heading color</span>
<span className="text-body color-body">Body color for running text.</span>
</div>
))}
</div>
)
}With the default tokens all three roles are black in the default mode and white in dark; a brand palette usually gives them distinct values. See Themes and backgrounds.
Font familiesLink to this section
font-geist (one class per token font family) sets only the font family, for text that should use a token font without the rest of a text style. The font files themselves are loaded by your project; see Fonts.
Responsive and state variantsLink to this section
Font size, line height and letter spacing are responsiveSizing tokens, so a text style changes per breakpoint without a prefix. With the default tokens text-h1 is 33px on sm, 43px on md and 54px on lg; the full table is in Typography tokens.
To switch to a different style at a breakpoint, prefix the class: text-h3 lg:text-h1 keeps a heading at the h3 size until lg. State variants such as hover:color-heading work as well.
The text style classes sit in Systhema's utilities.systhema sub-layer, so a Tailwind utility on the same element overrides one property and keeps the rest: text-h2 font-normal is an h2 at regular weight. See Cascade layers.
CustomizingLink to this section
A text style combines tokens from three collections: the family and weight from font, the size, line height and letter spacing from responsiveSizing (typography.*), and the composite itself from the text styles. text-h1 reads --font-h1-font-family, --font-h1-font-weight, --typography-h1-font-size, --typography-h1-line-height and --typography-h1-letter-spacing. Change a value in Figma, or override the token in systhema.config:
const config: SysthemaConfig = {
customTokens: {
font: { h1: { fontFamily: 'Fraunces, Georgia, serif' } },
responsiveSizing: {
lg: { typography: { h1: { fontSize: '64px', lineHeight: '68px' } } },
},
},
}customTokens.textStyles overrides a composite or adds a new one, which becomes a class named after its key ('Display Hero' becomes text-display-hero). See Text styles and Fonts. blocks.typography: false removes the text style and color classes.