Guides
Working with type
The type scale, and the times it is right to size something by hand.
Type sizes come from your type scale, and there is no way to produce one that is not on it. What you get instead is a scale you can drag along.
Sizing by hand
Drag a corner of any text element. The type scales under your hand and settles onto the nearest size in your scale when you let go, with a badge naming what it will land on as you go.
Corners size the type. Edges still resize the box and set margins, because that is what those edges are.
Two things worth knowing:
It settles, so it moves when you release. You drag to 39px, it lands on
text-xxl, and the text visibly changes size at that moment. That is the rails
working — the token is what gets written, not the number under your hand.
Past the top of the scale it keeps growing, then comes back — unless you hold ⇧. There is nothing above the largest size to land on, so a plain drag returns to it. That is the snap doing what it says.
Off the scale
Hold ⇧ while dragging the corner. The type stops snapping and keeps whatever size you leave it at. The hint says off the rails the whole time it is held, so the difference is visible before you let go rather than after.
That is the gesture most people reach for, and it is the same ⇧ that takes a
spacing drag, a corner radius and a border off their scales. It is also the
answer to a heading that will not grow past text-display: a plain drag has
nothing above the largest token to settle on, so it comes back to it.
The same escape is on the value as well: drag the size itself — the value on the Size row, or the Type size icon on the editing bar. Sideways steps through the scale in size order, and ⇧ leaves it.
That is the whole escape, and it exists because a scale you cannot leave is not a constraint, it is a straitjacket. Everywhere else in the app ⇧ already meant this — a spacing drag, a corner, a border — and type was the one place it did not, for no better reason than that type had no drag for ⇧ to modify.
What you get afterwards is not a dead end either. The row shows the real size, marks it with a dot, and opens a field you can type into; every token chip is still there to snap back onto the scale with one click.
The dot is worth reading. It is a fact rather than a warning: an element holding a number of its own will not move when you remap the scale, and the whole point of the two layers is that everything moves together. Sometimes that is exactly what you want. Sometimes it means the scale is wrong and the honest fix is in the design system.
Choosing a size
The Type size category on the editing bar, or Size under Typography.
Sizes are grouped and the one that belongs to this element is marked as its
default — h1 for an <h1>. But the whole scale is offered underneath, because
an <h1> set at text-xs is a perfectly ordinary thing to want. It is a
default, not a rule.
Each one shows the size it actually comes out as at the canvas’s current
width — h1 default · 51px, text-display 102px. A fluid token is a clamp()
of three numbers in two units, and nobody can read one of those as a size, so it
is measured rather than parsed. Drag the width scrubber and the numbers move,
which is the point: a scale that looks right at 1280 and collapses at 480 is
something you should be able to see before you ship it.
If a size looks smaller than you expected, this is where to check. Either the token is doing what the scale says at this width — go and change the ratio in the design system — or you are not on the token you thought you were.
Stroke means the letters
On text, Stroke outlines the type — the thing a designer reaches for the word to do. It used to give a border round the box, which is a different thing that happens to share a name, and left the letters unreachable without knowing to look under Typography.
The box’s own edge is still there, under the same section below a rule that says Around the box, so both are available and neither is a surprise. On anything that is not text, Stroke means what it always did.
The rest
Typeface, Weight, Leading, Tracking, Slant, Caps and Underline are all on the editing bar as well as in the panel — the first four come from their own scales, and those are the ones that offer both layers.
Everywhere else, a scale with a Layer 2 offers Layer 2 only: picking a primitive would mean holding a raw value that remapping the scale will never move. Type is different. A design system names three weights — heading, body, bold — and a designer still wants 500, which is a real step on a real scale rather than a number somebody invented. The same is true of the tracking steps and the leading ratios: there, the numbered steps are the vocabulary, and the named pair sits on top of them rather than replacing them. Line length is typed, in characters. It sets how wide a block of text is allowed to get before it wraps, and around 60ch is the classic comfortable reading width. It is the one typographic size worth setting by hand: no scale can say it, because it is about the number of characters rather than a distance.
Slant, caps and underline
Slant and Caps offer your design system’s own decisions first —
--style-heading, --transform-heading and their body equivalents — then the
plain words: Upright / Italic, and As typed / CAPS / lower / Title
Case.
Both are there because a system says things like “headings are uppercase”, and neither is only tokens because no system has a token meaning italic — italic is a decision about one run of text, not a rule about a scale. Picking a keyword is not marked as off-scale: it is a named CSS value, not a measurement somebody invented.
Not offered: --h1-style and its siblings, which do match the pattern. Those are
the reset’s bindings — the line that makes an <h1> pick up the heading
treatment — so an element referencing one would be saying “be styled like an h1”
rather than “be italic”.
Underline is None, Underline or Struck through, and has no scale by design.
Shadow and outline
Under Typography, Text shadow and Outline apply to the letters.
That matters because the box has its own pair, under Style & depth: Shadow
is a box-shadow on the rectangle around the text, and Stroke is a border
on it. Both are legitimate — a heading with a fill wants a box shadow, and a
rule under a heading is a border — so nothing was taken away. Which one you get
is decided by which section you are in: Style & depth is the box, Typography
is the text.
Text shadow is Across, Down and Blur, plus a colour from your palette. It is
typed rather than picked from a scale because there is no scale for it: the
--shadow-* tokens are box shadows and carry a spread radius, which
text-shadow does not accept — offering them would write CSS the browser
throws away. When your design system grows a --text-shadow-* family the scale
will appear here on its own.
Outline is a thickness and a colour. It is emitted with paint-order: stroke fill, which is not optional: a text stroke is painted centred on the edge of
each letter, so without it half the stroke eats into the letterform and the type
visibly thins. At 2px the difference between the two is the difference between
an outlined heading and a broken one.
Two treatments in one sentence
A heading whose second line is a different colour is one of the commonest things
a designer asks type to do, and the obvious route — two headings, one of them
coloured — is two <h1>s with half a sentence in each. The document outline says
something untrue and a screen reader reads it that way.
So: select the words while editing and give them a styling tag.
Double-click into the text, select a run, and press T on the editing bar. It offers three things, in the order you would reach for them:
| Already in this design | tags this document is using, so a second line matches the first without inventing a name |
| From the design system | the utilities in globals.css — .accent and its neighbours |
| New styling tag | a class of this block’s own, named after it |
A new tag is named the way everything else here is named: a .hero__title gets
.hero__title-em. The panel then points at that tag, with the banner across the
top saying so, and every control in it writes to the tag rather than to the
heading — colour, weight, a gradient, whatever. Back to the element returns.
What lands in the markup is a real span:
<h1 class="hero__title">Everything a web <span class="hero__title-em">studio runs on</span></h1>
and an ordinary rule beside it. One heading, one sentence, and a developer reads the class and knows what it is for.
A design-system utility is applied, not edited. Choose .accent and the
words get it, but the panel does not retarget: that class is shared by every page
on the site, and changing it from inside one heading would change all of them.
It is edited in the design system, which is where it lives.
To take a tag off, select the words again and choose Remove.
Editing the words
Double-click on the canvas and type. You are editing at the size, weight and colour the text will really be, which is the point — a field on the far side of the window tells you nothing about how the line will break.
Enter commits, Escape cancels, Shift+Enter makes a new line.