Skip to main content

Typography

Typography in EDS has three roles on two typefaces. You pick a role by what the text does and a step by how large it should be, and density adjusts the size for you.

Version: EDS 2.0 (beta)

These pages document the typography in the Beta. If you are coming from Latest, or from the earlier beta, the token names have changed, and so has the way line height and weight work, so please start with coming from an earlier version.

Here is one line of interface text, with every property set by a token:

Pipeline pressure
Comfortable density. Every value on this diagram is read back from the browser, so it follows the density it is rendered in.
.label {
font-family: var(--eds-font-family-ui);
font-size: var(--eds-typography-label-md-font-size);
line-height: var(--eds-typography-label-md-line-height);
font-weight: var(--eds-font-weight-normal);
}

A step is a font size and the line height that goes with it. Set the line height wherever you set the font size, because text without its own line height inherits one from its parent.

Three roles​

Every piece of text takes one of three roles. Two typefaces cover them: Equinor for headers, and Inter for everything else.

RoleTypefaceStepsWeightsUse it for
typography.headerEquinorxs to 4xlmediumtitles: the headings of pages and sections
typography.labelInterxs to 5xlnormal, medium, boldsingle-line functional text: buttons, navigation, table cells, form labels, captions
typography.bodyIntersm to 3xlnormal, boldrunning text that wraps: paragraphs and descriptions

Choosing a role​

Ask what the text is, and whether it wraps:

  • It is a title: header. The heading of a page or a section.
  • It stays on one line: label. A button, a menu item, a table cell, a form label.
  • It wraps, or could: body. A paragraph, a description, a message that runs to sentences.

The size of the text does not change its role. A key figure, such as the headline value "312 bar" on a dashboard, is label because it is a value on one line, even when it is set larger than the page title.

body uses the same font sizes as label, with a line height of at least one and a half times the font size, so the eye can find the next line in a block of text.

The steps​

Each role has its own range of steps. Comfortable values, as font size / line height in px:

Stepheaderlabelbody
xs12 / 1610 / 16–
sm14 / 2012 / 1612 / 20
md16 / 2014 / 2014 / 24
lg18 / 2416 / 2416 / 28
xl21 / 2818 / 2418 / 28
2xl24 / 3221 / 2821 / 32
3xl28 / 3624 / 3224 / 36
4xl32 / 4028 / 32–
5xl–32 / 36–

A dash means the role has no such step. The values change with density, and the token reference lists them in all three densities. In running text we shorten the names, so typography.label.md becomes label.md.

Equinor's scale runs one step ahead of Inter's, so a header is larger than the label with the same step name. The type scale shows the two side by side.

Groups of steps​

Within each role, the steps fall into groups by where the text sits. Components use the smaller steps, and the page around the components uses the larger ones:

RoleGroupStepsUse
headerPage title4xlthe h1, which names the page
Sections3xl, 2xlh2 and h3
Subsectionsxl, lg, mdh4, h5 and h6
Headings with no default elementsm, xspage-chrome headings that must look smaller than an h6
labelInside componentsxs to lgsingle-line component text, with md as the default
Page layoutxl to 5xltop-level navigation, the app name, and key figures
bodyInside componentssm, mdhelper text under a field, and text that wraps inside a component
Pagelg, xlrunning text, and the ingress: the introduction under the page title
Page layout2xl, 3xlintro text on front pages, pull quotes, and text read from a distance

The decision table gives the step for each use, and heading levels gives the header step for h1 to h6.

Weight​

Weight is set separately from size. A text style combines a step with one of three weights:

TokenCSS custom propertyValueUse it for
font-weight.normal--eds-font-weight-normal400the default for label and body text
font-weight.medium--eds-font-weight-medium500every header, and label text that needs emphasis
font-weight.bold--eds-font-weight-bold700strong emphasis in label and body text, and <strong> and <b> on the web

Each role has a fixed set of weights, listed in the roles table. On the web, <em> and <i> set no weight: they keep the weight of the text around them and turn italic.

Weight 400 has three names

They all mean the same weight. The token is font-weight.normal, which is what you write in code. The Figma text styles call it default, as in label/md/default, and Figma's font picker shows the Inter weight as Regular.

Typefaces​

TokenCSS custom propertyTypefaceUsed by
font-family.header--eds-font-family-headerEquinorheader
font-family.ui--eds-font-family-uiInterlabel and body

Loading the fonts​

The EDS variable font stylesheet loads both Equinor and Inter:

<link
rel="stylesheet"
href="https://cdn.eds.equinor.com/font/eds-uprights-vf.css"
/>
equinor-font.css does not include Inter

The older equinor-font.css stylesheet only includes Equinor. With it alone, every label and body style, which is most of an interface, falls back to a generic sans-serif without any error.

Density​

The data-density attribute resizes the interface. It moves type size and line height together, along with spacing, so the proportions you designed are kept:

<div data-density="compact">…</div>

Compact takes the size and line height of the next smaller step, and Relaxed the next larger. So a label.md in Compact is set like a label.sm in Comfortable. Switch the density below and watch the values change while the token names stay the same:

Pipeline pressure
The same four tokens at the density selected above.

Comfortable is the default, used where no data-density is set. Density on the spacing page explains which density to use where, and how density works explains the rule for type.

Principles​

The decisions about size, weight and line height on these pages follow four principles.

Safety through legibility​

Our main goal in typography is safety, and we reach it through legibility. A change that makes text harder to read accurately and quickly counts as a regression, even when it improves something else.

Text sets the proportions​

We build from our minimal unit, the text, and from there we define the proportions for padding, line height and gaps. Line heights come from the same scale as spacing, so text and layout share one rhythm, and a component's height follows from its text and padding rather than being set on its own.

Values are adjusted by eye​

A consistent visual rhythm makes an interface easier to use, so when a value that follows the scales looks wrong on screen, we change the value. The header line heights are one example: they are chosen for how Equinor looks, and most of them sit above the step their font size would give. Header line heights lists them.

Fixed choices and guidance​

We keep the options few enough to choose between quickly, and leave room where teams' needs differ. Some choices are fixed: each role has a set of weights, and a header is always medium. Others are guidance: the header step for each heading level is a starting point that a layout can depart from.

Coming from an earlier version​

Latest is the version most products use today, with the components and the Figma library in production. The earlier beta is the beta typography from before these tokens, which used the Figma Typography component. For developers, Latest is eds-core-react and eds-tokens 2.x, and the earlier beta is the ui-body tokens.

From Latest​

Re-pick each piece of text with the question in choosing a role and the groups of steps, instead of looking for its old size on the new scale. They ask what the text does and where it sits, so they give the same answer on every page, whatever the old layout used. Component text does not always keep its old size either: a field label is 12px in Latest, and label.md in the Beta.

From the earlier beta​

The earlier beta had one Inter role, ui-body, with two line heights per step, and weight, tracking and baseline trim per step as well. The Beta splits that role in two and moves weight out of the size tokens:

Earlier betaBeta
--eds-typography-ui-body-{size}-font-size with -line-height-squished, for UI text--eds-typography-label-{step}-font-size and -line-height
--eds-typography-ui-body-{size}-font-size with -line-height-default, for prose--eds-typography-body-{step}-font-size and -line-height
--eds-typography-header-{size}-font-size and -line-height-*--eds-typography-header-{step}-font-size and -line-height
--eds-typography-header-font-family, --eds-typography-ui-body-font-family--eds-font-family-header, --eds-font-family-ui
--eds-typography-{family}-{size}-font-weight-normal--eds-font-weight-normal
--eds-typography-{family}-{size}-font-weight-bolder--eds-font-weight-medium, the same weight
--eds-typography-{family}-{size}-font-weight-lighternone. The lighter weight is gone, so use --eds-font-weight-normal
--eds-typography-{family}-{size}-tracking-*none. Letter spacing is the typeface's own, with no token
.eds-heading-bold, .eds-heading-lightnone. Headers have one weight
data-density="spacious", or no attributeno attribute, which gives Comfortable
data-density="comfortable"data-density="compact"

For ui-body, the step names carry over, and the Comfortable sizes are the spacious sizes of the earlier beta, rounded to whole pixels, up to 5xl. There is no 6xl. Spacing renamed its densities in the same way, as the warning on the spacing page describes.

Three other things changed that no token mapping shows:

  • There is no baseline trim. The earlier beta trimmed multi-line text to the baseline with text-box. The Beta does not trim: a line of text is as tall as its line height, in Figma and in code.
  • Weight no longer changes with size. In the earlier beta, each step had its own weights. Now a role has a fixed set, and a large header uses the same medium as a small one.
  • The Figma Typography component is gone. Text is set with text styles, such as label/md/default, which you can find with their sizes in the Figma style list.

The first Beta releases (eds-tokens 3.0.0-beta.1 to 3.0.0-beta.7) named the Inter role ui and had bolder and lighter weights. ui is now label, with the same values, or body for text that wraps. bolder is now medium, at the same weight, and lighter is removed.

Where to go next​

  • The type scale: the scales under the names, where line heights come from, and how density maps onto them.
  • Using typography: which role and step to use, the header step for each heading level, worked examples, and the mistakes to avoid.
  • Token reference: every token and every value, in all three densities.