04 · Typography Utilities¶
Text is most of what people read on a page, so type utilities are among the ones you'll
use most. Tailwind's type scale is designed so that the common case needs one class —
text-lg sets a size and a matching line height — while every property stays
individually adjustable. This lesson covers the scale, how the paired line heights work
under the hood, and the wrapping and truncation utilities that fix most text layout
problems.
Font size: a scale with built-in line heights¶
| Class | Font size | Default line height |
|---|---|---|
text-xs |
0.75rem | 1rem |
text-sm |
0.875rem | 1.25rem |
text-base |
1rem | 1.5rem |
text-lg |
1.125rem | 1.75rem |
text-xl |
1.25rem | 1.75rem |
text-2xl |
1.5rem | 2rem |
text-3xl |
1.875rem | 2.25rem |
text-4xl |
2.25rem | 2.5rem |
text-5xl … text-9xl |
3rem … 8rem | 1 |
(Line heights are written as ratios in the theme — --text-3xl--line-height: calc(2.25 /
1.875) — which works out to the rem values above at each size.)
Here is text-lg as generated:
.text-lg {
font-size: var(--text-lg);
line-height: var(--tw-leading, var(--text-lg--line-height));
}
The line height uses var(--tw-leading, …): if a leading-* class has set
--tw-leading on the element, use that; otherwise use the size's default. That's how
text-lg leading-tight works regardless of the order the rules appear in the stylesheet.
Size and line height in one class¶
A slash sets both at once:
text-sm/6, text-base/relaxed (named leading) and text-2xl/[1.1] (arbitrary) all work.
Leading and tracking¶
.leading-tight {
--tw-leading: var(--leading-tight);
line-height: var(--leading-tight); /* 1.25 */
}
.tracking-wide {
--tw-tracking: var(--tracking-wide);
letter-spacing: var(--tracking-wide); /* 0.025em */
}
leading-none (1), leading-tight, leading-snug, leading-normal, leading-relaxed,
leading-loose, or a spacing number (leading-6 = 1.5rem). Tracking runs from
tracking-tighter to tracking-widest. Large headings usually look better with slightly
negative tracking (tracking-tight) and tighter leading.
Family, weight, style¶
<p class="font-sans">system UI sans-serif stack</p>
<p class="font-serif">serif stack</p>
<code class="font-mono">monospace stack</code>
<p class="font-light">300</p> <p class="font-medium">500</p> <p class="font-semibold">600</p> <p class="font-bold">700</p>
<p class="italic">italic</p> <p class="not-italic">cancel it</p>
The default font-sans stack is the operating system's UI font with fallbacks. Using your
own fonts is a theme change (Level 2 · 02).
Decoration, case and alignment¶
<a class="underline decoration-2 decoration-sky-500 underline-offset-4 hover:decoration-4">Link</a>
<p class="uppercase tracking-wider text-xs">Label</p>
<p class="text-center md:text-start">Centred on phones, start-aligned from md</p>
<span class="line-through">£42</span>
Prefer text-start / text-end over text-left / text-right — they follow the text
direction, so they mirror in right-to-left languages.
Wrapping, truncation and clamping¶
These fix most "text breaks my layout" bugs:
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.line-clamp-3 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.text-balance { text-wrap: balance; } /* even line lengths for headings */
.text-pretty { text-wrap: pretty; } /* avoid a lonely last word in paragraphs */
.break-words { overflow-wrap: break-word; }
.wrap-anywhere { overflow-wrap: anywhere; }
truncate— one line with an ellipsis. Needs a width constraint, and inside a flex item the item also needsmin-w-0.line-clamp-{n}— up to n lines, then an ellipsis.text-balanceon headings is one of the cheapest visual improvements you can make.- Long URLs and code in user content:
break-wordsorwrap-anywhere.
Truncating hides information. If the full text matters, make sure it's reachable — a link
to the full item, or a title attribute for mouse users as a supplement (not a
replacement).
Worked example: an article header¶
<header class="mx-auto max-w-2xl">
<p class="text-sm font-semibold uppercase tracking-wider text-sky-700">Techniques</p>
<h1 class="mt-2 text-4xl font-bold tracking-tight text-balance text-gray-900 md:text-5xl">
Why roasting tomatoes concentrates their flavour
</h1>
<p class="mt-4 text-lg/8 text-pretty text-gray-600">
Heat drives off water and caramelises sugars. Here's what that means for your soup.
</p>
<p class="mt-6 text-sm text-gray-500">
By Priya Rao · <time datetime="2026-09-30">30 September 2026</time>
</p>
</header>
A small uppercase eyebrow label with wide tracking; a large, tight, balanced headline that
grows at md; a lead paragraph with generous text-lg/8 leading; muted meta text. Every
size comes from the scale, so it harmonises with the rest of the site.
How It Actually Works¶
Typography utilities are a good example of how v4 composes related properties through private custom properties rather than overriding each other:
text-lgwritesline-height: var(--tw-leading, <default>).leading-tightwrites both--tw-leadingandline-height.
Both rules set line-height and live in the same layer, so the one later in the
stylesheet would normally win. In the generated file, .text-lg came before
.leading-tight — and even if it hadn't, text-lg's var(--tw-leading, …) would pick up
the value leading-tight set on the same element. We checked both class orders on an
element: class="leading-tight text-lg" and class="text-lg leading-tight" each computed
to a line height of 22.5px (1.25 × 18px). The order of class names in the HTML never
matters; only the order of rules in the CSS does, and Tailwind controls that. The same
trick powers --tw-tracking, --tw-font-weight and the shadow and ring stacks you'll see
in lesson 05.
These --tw-* variables are registered with @property and inherits: false, so a
leading-tight on a parent doesn't leak into children through the variable — each element
only sees its own. We put leading-loose on a div and text-lg on a paragraph inside
it: the paragraph's line height was 28px — text-lg's own default (1.75rem) — not the
parent's loose leading.
Common mistakes¶
truncateon a flex child withoutmin-w-0— the text never truncates.- Setting
leading-*on a parent and expecting a child'stext-*to use it — the--tw-leadingvariable doesn't inherit; putleading-*on the same element astext-*, or usetext-lg/7. - Uppercase for long passages — hard to read; keep it for short labels.
- Hard-coded
text-leftthat doesn't mirror in RTL. - Too many sizes on one page. Pick four or five steps from the scale and reuse them.
Exercise¶
- Build the article header. Resize across
mdand check the headline's computed font size and line height in devtools. - Make a card title that truncates to one line, inside a flex row next to an icon. Make it
fail without
min-w-0, then fix it. - Clamp a product description to three lines with
line-clamp-3. - Put
leading-looseon a parentdivandtext-lgon a child paragraph. Check the child's line height. Then moveleading-looseonto the child.