在一句已经强调过的话里再强调其中一个词,它不会倾斜得更厉害,反而 站直了。把 LaTeX 的 \emph{...} 嵌套起来,字形会逐层翻转:斜体、直立(罗马体)、再斜体。换成 \textit 做同样的事却毫无动静——叠多少层,每一层都还是斜体。这个差别不是偏好问题。\emph 写下的是「此处需要强调」这个 含义,而不是「把它倾斜」这条指令,至于这个含义长什么样,是之后才决定的。本页顺着这个切换机制往下走,谈 \em 与 \emph 之间出人意料的分歧、斜体校正 \/,以及在 LaTeX 里画一条下划线为什么比想象中麻烦——所有数字都来自实际编译。
\emph 与 \textit 的区别
\emph 会看上下文再决定,\textit 则无条件倾斜。 周围是直立体时,\emph 把参数排成斜体;但在本来就是斜体的文字里,同一个 \emph 会把参数变回直立。它的目的是「与正文区分开」,所以当正文本身是斜的,站直反倒更能达成目的。\textit 没有这层判断。在已是斜体的段落里用它,外观毫无变化——本想强调的那个词彻底融进了周围。这就是「强调该用 \emph 而非 \textit」的首要理由。
% nesting the two commands, side by side
\emph{outer \emph{inner \emph{deepest}}}
\textit{outer \textit{inner \textit{deepest}}}把这两行排出来,并打印每一层 NFSS 当前保存的 字形属性,差别一望而知。\emph 是 it → n → it → n,每层翻转一次;\textit 报告 it → it → it,纹丝不动。而且 \emph 看的并不是「是不是斜体」,而是「此刻是否倾斜着」。在 \textsl{...}(倾斜体)里用 \emph,内容照样回到 n(直立);在 \textbf{...} 里,粗细 bx 被保留,只有字形变成 it,于是调用的是粗斜体(Computer Modern 中是 cmbxti10)。正因为各轴彼此独立,强调才能叠上去而不破坏粗细。
| 上下文 | \emph 得到的字形 | \textit 得到的字形 |
|---|---|---|
upright body text | 斜体(it) | 斜体(it) |
inside \emph | 回到直立(n)——强调可见 | 仍是斜体——强调消失 |
inside \textit | 回到直立(n) | 仍是斜体(无变化) |
inside \textsl | 回到直立(n)——任何倾斜都算 | 被改写为斜体(it) |
inside \textbf | 斜体,保留粗细 bx | 斜体,保留粗细 bx |
italic correction | 自动加入 | 自动加入(声明形 \itshape 不会) |
when to use | 句中的强调——凡是要表达含义之处 | 书名、学名、外来语——当倾斜本身就是目的 |
为什么嵌套之后会回到直立
答案就在定义本身。LaTeX 内核 latex.ltx 的第 11172 行只有一句:\DeclareTextFontCommand{\emph}{\em}。往上十行,第 11162 行是 \DeclareTextFontCommand{\textbf}{\bfseries}。也就是说,\emph 根本不是字体命令,而是 把切换声明 \em 包装成带参数的形式——与把 \bfseries 包装成 \textbf 出自同一条流水线。反转的能力属于 \em 而非 \emph,\em 会先查看当前字形再决定去向。于是这个判断在每一层嵌套里各自独立地发生。
这个设计与 Web HTML 中 <em>(强调)和 <i>(斜体)的分工完全是同一个思路,而 LaTeX2e 从 1994 年起就已经这样实现了。<em> 承载「被强调」的含义,具体外观交给 CSS;在 LaTeX 里同样,正文中只用 \emph 写下 含义,外观交给类文件或导言区决定。实际好处很具体。若日后决定「强调改用粗体而非斜体」,只需改动定义所在的那一处,整篇文档随之改变,正文一字不动。反之,若把 \textit{...} 撒进正文,每次方针变更都要逐处找出并重写;而且 \textit 同时也是书名的正确写法,连靠查找替换来区分这两种情形都做不到。
设计强调的层级(\DeclareEmphSequence)
斜体与直立交替 只是默认行为,导言区可以整体替换。为此提供的命令是 \DeclareEmphSequence,随 LaTeX News 31(2020 年)引入。它的参数是一串以逗号分隔的字体声明,依次对应第一级强调、第二级……。在此之前,LaTeX 只能在斜体与直立之间往返;有了这套机制,就可以自行规定:第一级用斜体,第二级用小型大写字母,第三级用斜体小型大写字母。
% in the preamble: italic, then small caps, then italic small caps
\DeclareEmphSequence{\itshape,%
\upshape\scshape,\itshape}- 若嵌套比列表更深 — 会改用
\emreset(默认为\ulcshape\upshape,即普通直立),再往下一级则从列表开头重新开始。用上面这个两项列表排到第五级,实测为it→sc→n→it→sc:重置落在第三级,循环从第四级恢复。 - 会有一次「聪明」的检查 — LaTeX 会确认给定的声明是否真的改变了当前字体;若不会,就跳过该级去试下一级,因为它假定你已手动切换到那个字体了。
- 想绕过检查就用
\emforce— 比如只改颜色的声明,字体属性纹丝不动而外观确实变了,检查就会误判。给该项加上\emforce,即使属性看起来没变也强制生效。
\em 和 \emph 该用哪一个
写稿请用 \emph{...}。\em 执行同样的切换,但不加斜体校正。 \em 是不带参数的 声明,要用花括号限定范围,如 {\em 只有这里}。反转的判断逻辑与 \emph 完全一样——或者说,正如刚才所见,\emph 里装的就是 \em。差别出在外包装:只有 \DeclareTextFontCommand 造出的带参数形式,才会在倾斜字形与下一个字之间塞进校正。实测 \textit{f}h 宽 10.74167pt,而 {\itshape f}h 只有 8.62222pt;\emph{f}h 是 10.74167pt,{\em f}h 是 8.62222pt。整整 2.11945pt 就这样丢了。若要用声明形,就得自己在倾斜段落末尾补上 \/。
斜体校正 \/ 究竟是什么
斜体校正是一个数值,说明某个字符向右伸出多少,它逐字存放在字体度量文件里。 倾斜的字形向右上方探出,但它的排版宽度(f 为 3.06665pt)并不把那部分算进去。于是紧随其后的直立字母就会与探出的部分相撞。TeX 的字体度量(TFM)从一开始就把这个探出量记作 CHARIC。cmti10 中 f 的 CHARIC R 0.211945——按 10pt 设计尺寸即 2.11945pt,与上一节测得的 \textit{f}h 与 {\itshape f}h 之差小数点后完全吻合。\/ 不过是一条指令:「把前一个字符的 CHARIC 作为空白插入」。顺带一提,直立的 cmr10 里 f 的 CHARIC 也不是零,而是 0.077779——那个钩同样探了出去。
说 \emph 和 \textit 会自动加入校正,并不意味着它们总是加。若紧随其后的是逗号或句点,校正就会被跳过。latex.ltx 第 11250 行的 \def \nocorrlist {,.} 就是这份清单——这些标点位置低,正好钻进探出部分的下方,再加空白反而显得脱节。实测也一致:\textit{f}. 与 {\itshape f}. 都恰好是 5.84444pt。反过来,若想阻止校正,就在参数内部放 \nocorr:\textit{\nocorr text} 抑制开头一侧,\textit{text\nocorr} 抑制末尾一侧。\nocorrlist 本身也能用 \renewcommand 替换,但默认的逗号与句点几乎不会带来麻烦。
% argument form: the correction is added for you
He was \emph{very} clever.
% declaration form: add \/ at the end of the slanted run
He was {\em very\/} clever.
% before a comma or period nothing is added anyway
He was \emph{very}, and cheerful too.
% to suppress it explicitly
\textit{slanted\nocorr}text为什么 \underline 不能跨行
\underline 根本不是正文命令,它只是让数学下划线能在散文里使用。所以它的内容会变成一个不可分割的盒子,无法断行。 定义从 latex.ltx 第 13309 行开始,在文本模式下展开为 $\@@underline{\hbox{#1}}\m@th$。\hbox 是原子性的,TeX 的断行机制伸不进它里面。把 \underline{alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu} 放进宽 150pt 的段落,编译会报 Overfull \hbox (170.25879pt too wide):加了下划线的短语向右边距突出了整整 170pt。一两个词没问题,一旦给整句加下划线就崩溃了。连字(hyphenation)在其内部也会同时停止。
下划线本来就不是金属活字排版的工具,而是 为打字机发明的替代品。在一台既没有斜体也没有粗体的机器上,要表达「我强调了这里」,唯一的办法就是把滚筒退回一行敲一排下划线。用真活字排版的印刷厂没有这种需要,所以书籍不用下划线——LaTeX 的标准文档类也因此没有把下划线作为强调手段。当你想加下划线时,先确认自己真正需要的是一条线,还是强调。强调用 \emph,书名用 \textit,文档层级用 \section 一族;几乎每一种情况都已有更合适的工具。真正需要那条线的,是线本身被规定的场合:审稿人的批注要求、法律文书的体例、语言教材里的填空栏。
可以跨行的下划线 — ulem 与 soul
若需要能跨行的下划线,就加载 ulem 或 soul。二者都随 TeX Live 2024 一同分发,无需另行安装。 在刚才那个 150pt 宽的段落里,\underline 溢出了 170.26pt,而 ulem 的 \uline{...} 与 soul 的 \ul{...} 溢出都只有 0.30pt——也就是说,它们像普通文字一样正常折行。ulem 由 Donald Arseneau 自 1989 年起维护,除 \uline 外还有 \uuline(双下划线)、\uwave(波浪线)、\sout(删除线)、\xout(划掉)。soul 由 Melchior Franz 于 1998 年发布,现由 Oberdiek Package Support Group 维护;除 \ul 外,它还能处理并非画线的强调形式——\so(疏排字距)、\st(删除线)、\hl(荧光标记)。
这里有一个著名的陷阱:仅仅加载 ulem,全文的强调就会统统变成下划线。 ulem.sty 的文件头明确写着,在 LaTeX 中该宏包会把强调文本的斜体替换为下划线,而第 313 行的 \def\ULforem{\useunder{\uline}{\em}{\emph}} 把 \em 与 \emph 整个接管了。实测:素加载 ulem 时,\emph{word} 的盒子深度为 2.9pt——那是挂在基线以下的横线;紧接 \normalem 声明之后,同样的 \emph{word} 深度回到 0.0pt。也就是说,写下 \usepackage{ulem} 的那一刻,稿件里每一个 \emph 都变成了下划线。若想保留正常的强调而只用下划线功能,请写 \usepackage[normalem]{ulem}。 这是投稿前查看 PDF 时脸色发白的经典事故,所以加了 ulem 之后务必通篇复查。
% keep \emph italic; take only the rule-drawing commands
\usepackage[normalem]{ulem} % \uline \uuline \uwave \sout \xout
% \usepackage{soul} % \ul \so \st \hl
\uline{this underline breaks across lines just like ordinary text}
\sout{deleted} \quad \uwave{doubtful}强调用到什么程度算多
一个经验法则:同一段里出现两处以上强调,就是该改文字而不是改字体的信号。 强调之所以有效,是因为周围没有被强调。一页上散布得越多,每一处看上去分量就越接近,最后哪儿都不突出。强调真正见效是在修改阶段,而不是写作当下。起草时给重要词加 \emph 无妨,但提交前要重读一遍,想想能否改用句子结构本身来区分定义、对比、警示与结论。在结构承担了这项工作的文字里,强调只会留在「读者绝不能错过的那一点」上。顺带一提,中文正文里斜体作为字形往往并不自然,切换字体或使用着重号可能更符合读者预期;请按所在领域与文档类的惯例决定。
- 用于术语首次出现。 把刚定义的术语用
\emph标出,日后就能机械地把这些位置收进索引或术语表。 - 把外观需求分开。 书名、学名、外来语的斜体归
\textit。与强调混在一起,改变强调外观那天它们会被一并牵连。 - 不要批量替换成
\textbf。 若只需改变外观,就在导言区用\DeclareEmphSequence改。抹掉正文含义的替换无法挽回。 - 按文档统一定策略。 若强调的样子逐章不同,读者会误判重要性本身。
- 提交前搜索
\textit{。 确认其中没有被当作强调的替身,也确认\emph没有在标题和图表说明里泛滥。