Line height is the typography property that most directly shapes reading experience and the one most often set without thought. Too small, and lines crowd into a dense block; too large, and paragraphs feel loose and meandering; and the same line-height value produces visibly different results across typefaces because each font carries its own metrics. PDF export amplifies every mistake: on a scrolling web page, minor leading differences pass unnoticed, but a PDF is a static deliverable where every line's spacing is fixed into the file and judged at print size. dompdf.js computes line boxes and leading through the real typesetting engine, so the four ways of writing line-height — normal, a unitless number, a length, and a percentage — behave exactly as they do in the browser, and vertical-align gives the same control over inline elements. This guide explains what line-height actually computes, why the four value forms behave differently and how inheritance changes them, the half-leading mechanism that explains most visual surprises, how to align inline elements vertically including images and super/sub scripts, how CJK fonts and their metrics change the numbers, and the strategies that keep tables, lists, and multi-line elements consistent. The closing section answers the production questions. The goal is line height that is precise and intentional rather than approximately right. The order of sections matters: the value forms first, because every other decision depends on which one you choose; then the mechanics of line boxes, which explain the visual surprises; then vertical alignment, which shares the same line box; then the CJK specifics that change the numbers; and finally the strategies for tables, lists, and multi-line elements, where most real-world line-height bugs live.
line-height accepts four forms with materially different behavior. normal is derived from the font's metrics, roughly 1.2 times the font size but varying by typeface. A unitless number like 1.5 is a ratio of the font size, and children inherit the ratio, not a computed value. A length like 24px is an absolute value, and a percentage like 150% computes against the parent's font size — but both lengths and percentages hand the computed pixel value to children, which is where most line-height surprises come from.
The unitless number is the professional default: line-height: 1.6 scales with font size automatically, and children inherit the ratio itself, so a child with a different font size gets a proportional line height instead of a stale absolute value. Lengths and percentages are appropriate when a design mockup must be reproduced exactly, but in nested structures they freeze the computed value at the point of declaration, and the moment a child's font size changes, the line height no longer fits.
normal varies noticeably between typefaces: Source Han Sans SC's normal differs from many Latin faces, so mixed-script paragraphs using normal show inconsistent leading from line to line. Formal documents should set an explicit numeric line height, taking the spacing decision away from font metrics and giving mixed Chinese-English copy one consistent rhythm. This single declaration resolves the majority of leading inconsistencies in multilingual templates.
A subtle but real consequence: line-height also affects vertical rhythm across the page. If every block's height is a multiple of the body line height, the page grid aligns and page breaks land consistently; choosing the body line height first and deriving component spacing from it is a cheap way to make multi-page documents look composed rather than assembled.
line-height sets the height of the line box. The space left over after the text's content is placed is split evenly above and below the text — each half is called half-leading. Half-leading explains most visual surprises: with a large line-height the text sits vertically centered in its line box; with a line-height smaller than the font's em box, the glyphs are clipped or lines overlap, because the line box is simply too short for the type.
Inline content complicates the picture. The height of a line box is determined by the tallest inline content, not directly by line-height: an image or a large-font inline element stretches the line box, creating the illusion that line-height stopped working. The fix is deliberate: give inline images a vertical-align and a compatible line height, or make them block-level, and the declared line height takes effect again. The more mixed inline content a template has, the more this matters.
Line height also participates in pagination. A line box is the minimum unit of page breaking — it is never split across pages — so when a page bottom cannot fit one more line, the whole line moves to the next page, leaving whitespace at the bottom. Larger line heights make this bottom whitespace more frequent; multi-page documents need a balance between line height and margins, with explicit page breaks where needed so page bottoms stay clean instead of accumulating awkward gaps.
For documents with fixed-height cells or repeated rows, remember that the line height is part of the row's total height. Changing line-height without rechecking row heights silently changes pagination, so adjust both together when a template's vertical rhythm is being tuned. The same rule applies when swapping fonts in an existing template: a new face with different metrics changes every line box, so re-verify the rhythm after the swap rather than assuming the old values still hold.
A unitless 1.5-1.7 serves body text across most reading contexts; 1.3-1.5 raises density for tables and code; 1.8-2 creates air for covers and emphasis. Because the same ratio produces larger absolute spacing at larger sizes, headings do not need body-copy ratios: 1.2-1.3 keeps a large heading compact with a stable visual center, and the hierarchy reads correctly because each level's ratio matches its role.
vertical-align controls the vertical position of inline elements: middle aligns an image or icon with the text's midline, sub and super produce subscripts and superscripts, and baseline is the default alignment. The property applies only to inline elements and table cells — it is ignored on block-level elements. Images sitting on the baseline leave a visible gap below them; middle or bottom is usually the better choice in templates with icon-and-text rows.
Fixed lengths like 20pt are right for pixel-perfect mockup reproduction, but they carry an inheritance trap: children inherit 20pt, not a ratio, so a child at 16pt may end up with insufficient line height. Use fixed values for design-reproduction work and unitless numbers for content documents, and the two use cases stop contaminating each other. Decide per template, not per element.
When icons and text share a line, check the icon's intrinsic size against the line height. An icon taller than the line box stretches the whole line, and the vertical-align you chose no longer describes the visual relationship — sizing icons relative to the font size keeps the alignment honest.
<style>
body { font-size: 11pt; }
.tight { line-height: 1.3; }
.normal-lh { line-height: 1.6; }
.loose { line-height: 2; }
.icon-text { vertical-align: middle; }
.sup { vertical-align: super; font-size: 0.75em; }
.sub { vertical-align: sub; font-size: 0.75em; }
</style>
<p class="tight">Tight line height suits tables and annotations: high information density, but cramped at large sizes.</p>
<p class="normal-lh">1.6 is the comfortable range for Chinese body text: clear paragraphs and stable print output.</p>
<p class="loose">Loose line height suits covers and emphasis: breathing room and ceremony, but not for body copy.</p>
<p><span class="icon-text">◆</span> Icons and text align with vertical-align: middle</p>
<p>Chemical formula H<span class="sub">2</span>O and superscript x<span class="sup">2</span></p>
CJK typefaces carry different vertical metrics than Latin faces. Source Han Sans SC's default metrics differ visibly from common Latin fonts, so mixed-script paragraphs set to normal show uneven leading line to line. Setting one unitless line height for the paragraph equalizes the rhythm across scripts — the single most visible improvement available in Chinese document templates, and one line of CSS.
CJK punctuation interacts with line height too. Full-width punctuation occupies the same em width as Han characters, and with insufficient line height, punctuation visually collides with the lines above and below. Keep Chinese body line height at 1.5 or higher, and raise it to 1.6-1.7 at small sizes (10pt and below), so punctuation keeps breathing room and the document stays legible in print, where the collision cannot be scrolled past.
Custom fonts change the numbers again: different faces have different em boxes and ascender/descender metrics at the same font size, so the same line-height value produces different visual spacing. After switching fonts, recheck line height instead of trusting the old value; pinning font and line height together at template design time keeps the whole document stable, because a font swap then becomes a deliberate re-tune rather than a silent layout change.
A practical workflow for mixed documents: set the Latin font's line height, then measure the CJK lines at the same ratio and adjust once. The two scripts rarely need identical ratios, but they need compatible ones, and one measured adjustment beats endless trial and error. Document the chosen ratio in the template's style guide so future edits preserve the vertical rhythm instead of accidentally reintroducing metric-driven inconsistency. For accessibility-sensitive documents, err on the generous side: slightly more leading costs nothing visually but measurably improves readability for readers with visual impairments.
Tables are where line height control pays off most visibly. Multi-line cell text needs enough leading to stay readable, and too little makes the table feel cramped and oppressive. A uniform line-height: 1.4-1.5 across the table, combined with deliberate cell padding, controls total height predictably. Consistency matters across page breaks: a table split over two pages should show identical row spacing on both, so readers do not perceive the continuation as a different table.
List items follow the paragraph strategy, with one addition: the vertical gap between items belongs to margin, while line-height governs spacing within a line. The two properties have different jobs, and using them together gives controlled vertical rhythm. Multi-line list items align their second lines with the first, and insufficient line height makes those wrapped lines overlap — so when reviewing templates, check the two-line items specifically, because single-line items hide the problem.
Single-line elements like buttons and tags commonly achieve vertical centering by setting line-height equal to the container height. The trick works in PDF templates exactly as in the browser — until the text wraps. The moment content exceeds one line, the centered single line becomes a scrambled stack. For fixed-height containers whose text may wrap, flex with align-items: center is the robust replacement, and it costs nothing extra in the template.
When a fixed-height element must hold variable content, decide what breaks first: the height or the line count. If the height is sacred, size the font and line height so the worst-case content fits; if the content is sacred, let the height grow. Templates that leave this decision implicit produce the most unpredictable layout drift.
Multi-line elements inside fixed heights deserve one more warning: when a button or badge wraps to two lines, the line-height still applies per line, so the element grows by exactly one line's height — which may overflow its container or its parent's padding. Design fixed-height elements for their worst-case content, or let them grow, but never assume the content will stay on one line just because it did in testing.
Q: I set line-height but the PDF looks unchanged. A: Check for overrides from more specific selectors or inline styles; confirm the value itself is sensible, with the unitless number being the most reliable form; then look at what else inflates the line box — inline images and vertical-align stretch it, masking the declared line height. These three checks locate nearly every case.
Q: Text is clipped or lines overlap. A: A line height below the font's actual height guarantees this; raise it to at least 1.3 and check overflow settings. When a custom font has abnormal metrics, a unitless value overriding normal fixes most clipping, and a few fonts need a look at their internal line gap settings as well.
Q: Line spacing differs between the browser and the PDF. A: The engine is the same, so compare the exact styles: a missing rule or a different inherited value is usually the cause. Reproduce the template's computed styles in the browser and the difference becomes visible, then fix the declaration rather than the symptom.
Best-practice summary: unitless 1.5-1.7 for body text, 1.2-1.3 for headings, 1.4-1.5 for tables; one rhythm for mixed CJK-Latin copy; vertical-align: middle for images and icons; line-height for intra-line spacing and margin for inter-element spacing. This standard produces stable, professional line spacing, and multi-page documents break cleanly — the visible difference between typeset and merely generated.
Q: Line height is fine, but paragraphs have inconsistent spacing between them. A: That is a margin problem, not a line-height problem. Paragraph spacing belongs on margin-bottom, and line-height governs spacing within lines; when the two are conflated — for example, by inserting empty paragraphs — the spacing becomes unpredictable and pagination suffers. Give every paragraph an explicit margin-bottom and keep line-height for leading, and the vertical rhythm becomes consistent and controllable.
下面的按钮用 dompdf.js 在浏览器端实时生成 PDF,无需后端:
这是由 dompdf.js 渲染的示例 PDF 内容。