Typography

Typography Utilities and the Typography Plugin

Text utilities map one-to-one onto the font and text properties of Text Properties, with two conveniences. Every text-<size> class sets a matching line height from the theme (text-sm is 0.875rem on 1.25rem lines), and a slash overrides that line height in the same class: text-lg/7 means font-size: 1.125rem; line-height: 1.75rem. Because the size and weight scales are theme variables, adding --font-display: "Inter", sans-serif; or --text-tiny: 0.625rem; to @theme (Theme Variables) creates font-display and text-tiny classes.

Font and text utilities
Utility CSS
font-sans, font-serif, font-mono font-family: var(--font-sans) and so on
text-xs, text-base, text-4xl, text-9xl 0.75rem, 1rem, 2.25rem, 8rem, each with its line height
text-lg/7, leading-6, leading-none Size plus line-height: 1.75rem; 1.5rem; 1
font-light, font-semibold, font-black font-weight: 300, 600, 900
italic, not-italic, antialiased font-style; -webkit-font-smoothing: antialiased
tracking-tight, tracking-widest letter-spacing: -0.025em, 0.1em
text-center, text-start, align-middle text-align, vertical-align
uppercase, capitalize, normal-case text-transform
underline, decoration-2, underline-offset-4 Line, 2px thickness, 4px offset
truncate overflow: hidden; text-overflow: ellipsis; white-space: nowrap
line-clamp-3 Clamp to three lines (-webkit-line-clamp: 3)
text-balance, text-pretty, whitespace-pre-wrap text-wrap: balance, pretty; white-space
wrap-break-word, break-all, hyphens-auto overflow-wrap, word-break, hyphens
list-disc, list-inside, indent-8 list-style-type, list-style-position, text-indent: 2rem
tabular-nums, slashed-zero, font-stretch-condensed font-variant-numeric, font-stretch

Headings in a card usually need only three or four of these: text-xl/7 font-semibold tracking-tight text-balance. Use truncate for one-line labels in tables and navigation, line-clamp-* for card excerpts, and tabular-nums in price columns and timers so digits line up and stop jiggling as values change.

The typography plugin

Preflight (Preflight) removes every heading size, list bullet and paragraph margin, which is right for components and wrong for content you do not write class by class: Markdown output, CMS fields, documentation. The official @tailwindcss/typography plugin (version 0.5.20, github.com/tailwindlabs/tailwindcss-typography (https://github.com/tailwindlabs/tailwindcss-typography 6,473 )) restores a hand-tuned reading style under a single prose class. Install it with npm 2,036 install -D @tailwindcss/typography and register it in your stylesheet with @plugin "@tailwindcss/typography"; right after @import "tailwindcss";.

The @tailwindcss/browser build refuses plugins, so the demo compiles its stylesheet with the same v4 engine the build tools use: it imports compile() from the tailwindcss package, hands it the plugin module, and injects the CSS generated for the classes found in the page.

The prose class styling unclassed article markupHTML
<article class="prose prose-sm prose-slate m-4 prose-a:text-sky-700">
  <h2>Release notes 2.4</h2>
  <p class="lead">Rendered from Markdown, styled by one class on the wrapper.</p>
  <p>Run <code>npm update</code>, then read the <a href="#">migration guide</a>.</p>
  <ul><li>Builds are 30% faster</li><li>New <strong>dark</strong> theme</li></ul>
  <blockquote>Upgrade before the end of the quarter.</blockquote>
  <p class="not-prose rounded bg-slate-800 p-2 text-xs text-white">A not-prose widget</p>
</article>
<script type="module">
  import { compile } from "https://cdn.jsdelivr.net/npm/tailwindcss@4.3.3/+esm";
  import typography from "https://esm.sh/@tailwindcss/typography@0.5.20?deps=tailwindcss@4.3.3";
  const url = "https://cdn.jsdelivr.net/npm/tailwindcss@4.3.3/index.css";
  const content = await (await fetch(url)).text();
  const compiler = await compile('@import "tailwindcss"; @plugin "@tailwindcss/typography";', {
    loadStylesheet: async () => ({ path: "", base: "", content }),
    loadModule: async () => ({ path: "", base: "", module: typography }),
  });
  const classes = [...document.querySelectorAll("[class]")].flatMap((el) => [...el.classList]);
  document.head.insertAdjacentHTML("beforeend", `<style>${compiler.build(classes)}</style>`);
</script>
Browser output of Listing 5.27
Browser output of 27