强调 (\emph)

在一句已经强调过的话里再强调其中一个词,它不会倾斜得更厉害,反而 站直了。把 LaTeX 的 \emph{...} 嵌套起来,字形会逐层翻转:斜体、直立(罗马体)、再斜体。换成 \textit 做同样的事却毫无动静——叠多少层,每一层都还是斜体。这个差别不是偏好问题。\emph 写下的是「此处需要强调」这个 含义,而不是「把它倾斜」这条指令,至于这个含义长什么样,是之后才决定的。本页顺着这个切换机制往下走,谈 \em\emph 之间出人意料的分歧、斜体校正 \/,以及在 LaTeX 里画一条下划线为什么比想象中麻烦——所有数字都来自实际编译。

\emph\textit 的区别

\emph 会看上下文再决定,\textit 则无条件倾斜。 周围是直立体时,\emph 把参数排成斜体;但在本来就是斜体的文字里,同一个 \emph 会把参数变回直立。它的目的是「与正文区分开」,所以当正文本身是斜的,站直反倒更能达成目的。\textit 没有这层判断。在已是斜体的段落里用它,外观毫无变化——本想强调的那个词彻底融进了周围。这就是「强调该用 \emph 而非 \textit」的首要理由。

latex
% nesting the two commands, side by side
\emph{outer \emph{inner \emph{deepest}}}

\textit{outer \textit{inner \textit{deepest}}}

把这两行排出来,并打印每一层 NFSS 当前保存的 字形属性,差别一望而知。\emphitnitn,每层翻转一次;\textit 报告 ititit,纹丝不动。而且 \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 只能在斜体与直立之间往返;有了这套机制,就可以自行规定:第一级用斜体,第二级用小型大写字母,第三级用斜体小型大写字母。

latex
% in the preamble: italic, then small caps, then italic small caps
\DeclareEmphSequence{\itshape,%
  \upshape\scshape,\itshape}
  • 若嵌套比列表更深 — 会改用 \emreset(默认为 \ulcshape\upshape,即普通直立),再往下一级则从列表开头重新开始。用上面这个两项列表排到第五级,实测为 itscnitsc:重置落在第三级,循环从第四级恢复。
  • 会有一次「聪明」的检查 — 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)从一开始就把这个探出量记作 CHARICcmti10fCHARIC R 0.211945——按 10pt 设计尺寸即 2.11945pt,与上一节测得的 \textit{f}h{\itshape f}h 之差小数点后完全吻合。\/ 不过是一条指令:「把前一个字符的 CHARIC 作为空白插入」。顺带一提,直立的 cmr10fCHARIC 也不是零,而是 0.077779——那个钩同样探了出去。

\emph\textit 会自动加入校正,并不意味着它们总是加。若紧随其后的是逗号或句点,校正就会被跳过。latex.ltx 第 11250 行的 \def \nocorrlist {,.} 就是这份清单——这些标点位置低,正好钻进探出部分的下方,再加空白反而显得脱节。实测也一致:\textit{f}.{\itshape f}. 都恰好是 5.84444pt。反过来,若想阻止校正,就在参数内部放 \nocorr\textit{\nocorr text} 抑制开头一侧,\textit{text\nocorr} 抑制末尾一侧。\nocorrlist 本身也能用 \renewcommand 替换,但默认的逗号与句点几乎不会带来麻烦。

latex
% 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 一族;几乎每一种情况都已有更合适的工具。真正需要那条线的,是线本身被规定的场合:审稿人的批注要求、法律文书的体例、语言教材里的填空栏。

可以跨行的下划线 — ulemsoul

若需要能跨行的下划线,就加载 ulemsoul。二者都随 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 之后务必通篇复查。

latex
% 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 没有在标题和图表说明里泛滥。