Introduction
For years, a CSS reset meant zeroing margins, normalising list styles and not much else. Typography was left to the theme, to plugins, or to small JavaScript helpers that patched awkward line breaks after the page had loaded.
That is changing. Browsers now understand a surprising amount about how text should behave, from balancing the lines of a headline to trimming the invisible space above capital letters. Gathering the best of these features into a single typographic baseline can make a site feel more polished with very little extra code, provided you respect the places where browser support is still patchy.

Start With Predictable Rendering
The first job of any text baseline is to stop the browser making surprising decisions on your behalf. A few properties do most of the heavy lifting:
font-synthesis: noneprevents the browser from faking bold or italic styles when a font family doesn’t include them. Faux bold tends to look smudged, and faux italic is simply slanted upright lettering.text-size-adjust: none(alongside its-webkit-and-moz-prefixed versions) stops mobile browsers inflating text when a phone is rotated, which can otherwise knock a carefully sized layout out of shape.font-size-adjust: from-fontuses the font’s own metrics to keep the apparent size steadier while a fallback is swapped for the web font, softening that jarring jump during loading.
Smoothing hints such as -webkit-font-smoothing remain common, but they are platform-specific and divide opinion among developers, so treat them as optional extras rather than essentials.
Sizing Type to Its Container, Not the Screen
Fluid type built on viewport units has a blind spot: it scales with the browser window rather than with the space a heading actually occupies. A title in a narrow sidebar can end up sized as though it stretched across the full screen.
Container query units fix this. Once a wrapper is declared as a container with container-type: inline-size, its children can use the cqi unit, which is measured against the container’s width. Swapping vw for cqi inside a clamp() expression gives you a type scale that adapts whether a component lives in a wide article column or a slim card, with no extra media queries.
Tidier Line Breaks and Spacing
Several newer properties tackle the small details that make text look professionally set:
text-wrap: balanceevens out line lengths in short blocks such as headings and captions, so you don’t end up with one lonely word on the second line. It is designed for a handful of lines rather than long passages.text-wrap: prettyis aimed at body copy, adjusting breaks to avoid a single stranded word at the end of a paragraph without reflowing the whole block.text-wrap: stablesuits editable areas, where earlier lines shouldn’t jump about as someone types.text-box-trimandtext-box-edge(or thetext-boxshorthand) remove the half-leading above and below a line of text, making it far easier to align copy precisely with icons, borders or images. That means no more negative-margin hacks tuned to one particular typeface.
Combine these with a sensible line length, such as a maximum width of around 65ch on paragraphs, and long-form reading becomes noticeably more comfortable.

Hyphenation, Punctuation and Underlines
Automatic hyphenation depends on the browser’s language dictionaries, so it only works when the page declares its language correctly, for example lang="en-GB" on a British site. Left at its defaults, hyphens: auto can be heavy-handed, splitting short words or stacking several hyphenated lines one above another. Properties such as hyphenate-limit-chars and hyphenate-limit-lines let you rein that in, although Safari still relies on prefixed equivalents and support elsewhere is limited. Code samples and headings are best kept away from hyphenation entirely, since a broken word there usually reads as a mistake.
Hanging punctuation allows an opening quotation mark to sit just outside the text edge, so the left margin looks genuinely straight; for now this is largely a Safari feature. Underlines can be refined too: text-decoration-thickness: from-font uses the weight the type designer intended, text-underline-offset gives descenders some breathing room, and text-decoration-skip-ink breaks the line wherever letters dip through it.
Getting More From Variable Fonts and Numbers
Variable fonts often include an optical size axis, and font-optical-sizing: auto lets the typeface adjust its stroke contrast to the size it is rendered at. Where a font offers a grade (GRAD) axis, you can lower it slightly in dark mode, because pale text on a dark background tends to look heavier than the same weight on white. Unlike a weight change, adjusting grade leaves letter widths untouched, so nothing reflows.
Numbers deserve attention as well. Tabular, lining figures keep columns tidy in tables and price lists, while proportional old-style figures sit more naturally within running text. The font-variant-emoji property lets you choose colour or monochrome emoji explicitly, and font-variant-position can switch to a font’s purpose-drawn superscript and subscript glyphs where they exist.

Keep It Overridable and Test Carefully
Wrapping baseline rules in :where() gives them zero specificity, so a single class in your theme can override any of them. That matters, because these are opinionated defaults rather than universal rules. Older browsers simply ignore declarations they don’t understand, but that only works in your favour if the text still looks acceptable without the enhancements. Some of the properties covered here are experimental, and a few divide opinion among seasoned developers, so introduce them gradually and check the results across browsers and devices.
For small businesses the payoff is subtle but real: cleaner headlines, easier reading and a more considered feel, all without loading extra scripts. If the text on your website looks a little rough around the edges, a carefully chosen typographic baseline is one of the most cost-effective upgrades available.
Code Examples
A compact starting point for headings and body text:
:where(h1, h2, h3, h4) {
text-wrap: balance;
line-height: 1.2;
hyphens: manual;
}
:where(p, li) {
text-wrap: pretty;
max-width: 65ch;
}
Container-aware heading sizes for a card component:
.card {
container-type: inline-size;
}
.card h3 {
font-size: clamp(1.25rem, 1rem + 2.5cqi, 2rem);
}
Aligned figures in a pricing table, plus a feature check before trimming a badge’s text box:
.price-table td {
font-variant-numeric: tabular-nums lining-nums;
}
@supports (text-box: trim-both cap alphabetic) {
.badge {
text-box: trim-both cap alphabetic;
}
}











