为什么高度为零的 parbox 会占用垂直空间?

为什么高度为零的 parbox 会占用垂直空间?

假设我们有一份文档,其中有一段文本,后面跟着两个垂直空间框,后面跟着另一段文本。我认为我可以在垂直空间框之间插入一个高度为零的 parbox,而不会增加段落之间的空间。毕竟,它的高度为零。然而,我的假设并不正确,因此我的问题是额外的空间来自哪里。

\documentclass[11pt]{article}
\usepackage{blindtext}
\renewcommand{\familydefault}{\sfdefault}
\begin{document}

\blindtext

\vspace{1cm}

\parbox[c][0pt]{\linewidth}{} % When we add this line, the space between both paragraphs increases

\vspace{1cm}

\blindtext

\end{document}

下面您可以看到编译文档的屏幕截图(第一行),在第二行中我画出了我认为应该是什么样子的框。第一列描述了当我们用一个简单的字符串替换 parbox 时的情况。当然,该文本会占用一些空间。第二列描述了我预期插入 parbox 时的情况。从技术上讲,我们在 vspace 框之间得到了一条新线,但由于这条线在基线上方和下方的高度和深度均为零,因此该线“折叠”并且空间不会增加。第三列最终描述了实际情况。似乎零高度 parbox 引入了恰好一个的额外空间baselineskip。为什么会这样,基线究竟放在高度为的框中的什么位置baselineskip?我认为新线的基线与上部 vspace 框的底边之间的距离由该线中高度最高的元素决定(就像图片第 1 列中的“L”一样)。

在此处输入图片描述

答案1

让我们最小化这个例子

\documentclass{article}

\pagestyle{empty}

\showoutput

\begin{document}

Test

\vspace{30pt}% so we can see it better in the output

\parbox[c][0pt]{\linewidth}{}

\vspace{30pt}

Test

\end{document}

在控制台输出中我们看到

Completed box being shipped out [1]
\vbox(633.0+0.0)x407.0
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0
..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x345.0, glue set 455.9513fil
...\write-{}
...\glue(\topskip) 3.16669
...\hbox(6.83331+0.0)x345.0, glue set 311.33333fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/n/10 T
....\kern-0.83334
....\OT1/cmr/m/n/10 e
....\OT1/cmr/m/n/10 s
....\OT1/cmr/m/n/10 t
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue 30.0
...\glue 0.0
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 9.5
...\hbox(2.5+0.0)x345.0, glue set 330.0fil
....\hbox(0.0+0.0)x15.0
....\mathon
....\vbox(2.5+-2.5)x0.0
.....\glue 0.0 plus 1.0fil minus 1.0fil
.....\glue 0.0 plus 1.0fil minus 1.0fil
....\mathoff
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue 30.0
...\glue 0.0
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 5.16669
...\hbox(6.83331+0.0)x345.0, glue set 311.33333fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/n/10 T
....\kern-0.83334
....\OT1/cmr/m/n/10 e
....\OT1/cmr/m/n/10 s
....\OT1/cmr/m/n/10 t
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 30.0
..\hbox(0.0+0.0)x345.0

对应\parbox

....\hbox(0.0+0.0)x15.0                  % <- indent
....\mathon                              % <- start math mode
....\vbox(2.5+-2.5)x0.0                  % <- a \vbox from \vcenter
.....\glue 0.0 plus 1.0fil minus 1.0fil  % <- the glue for vertical centering
.....\glue 0.0 plus 1.0fil minus 1.0fil  % <- the glue for vertical centering
....\mathoff

因为该[c]选项使用内部数学模式来执行\vcenter,实际高度和深度为 2.5pt(因为公式轴的标准高度)。不过解释就在这一部分之前,即

....\glue(\parfillskip) 0.0 plus 1.0fil     % <- the paragraph for Test has ended
....\glue(\rightskip) 0.0                   % <- no \rightskip
...\glue 30.0                               % <- the \vspace{30pt}
...\glue 0.0                                % <- from \vspace implementation
...\glue(\parskip) 0.0 plus 1.0             % <- a paragraph has started
...\glue(\baselineskip) 9.5                 % <- vertical glue
...\hbox(2.5+0.0)x345.0, glue set 330.0fil  % <- a line

最后\hbox是包围 的内容\parbox,并且 前面是 的粘连,\baselineskip大小为 9.5pt:实际上,盒子的高度为 2.5pt,9.5 + 2.5 = 12( 的值\baselineskip)。

同样,你看到框后

....\penalty 10000                                  % <- from \par
....\glue(\parfillskip) 0.0 plus 1.0fil             % <- a paragraph has ended
....\glue(\rightskip) 0.0                           % <- no \rightskip
...\glue 30.0                                       % <- \vspace{30pt}
...\glue 0.0                                        % <- from \vspace
...\glue(\parskip) 0.0 plus 1.0                     % <- a paragraph has started
...\glue(\baselineskip) 5.16669                     % <- glue
...\hbox(6.83331+0.0)x345.0, glue set 311.33333fil  % <- the paragraph for Test

\penalty 10000因为 之后有一个空行\parbox,从而结束了该段落。

如果您这样做\parbox[c][0pt]{\linewidth}{X},那么您将看到更多内容:一条Overfull \hbox消息,因为缩进后跟一个使行宽更大的框。但是“Test”的两个实例之间的垂直间距不会改变,因为 parbox 垂直适合\baselineskip

换句话说,你有三个段落,它们之间有垂直间距。实际上,这些\vspace命令是一种转移注意力的花招。如果你考虑

\documentclass{article}

\pagestyle{empty}

\begin{document}

Test 1

Test 2

\parbox[c][0pt]{\linewidth}{}

Test 3

\end{document}

你得到

在此处输入图片描述

如果你使用的话,情况会有所不同\nointerlineskip\vbox to 0pt{}:这是并排比较:

\documentclass{article}

\begin{document}

\settowidth{\dimen0}{Test 1}

\parbox{\dimen0}{Test 1

Test 2

Test 3}%
\parbox{\dimen0}{Test 1

Test 2

\nointerlineskip\vbox to 0pt{}

Test 3}

\end{document}

在此处输入图片描述

答案2

首先值得注意的是,\vspace胶合不是一个盒子,TeX 的另一半盒子和胶合模型用于文本布局。

如果我将您的示例修改为

\documentclass[11pt]{article}
\usepackage{blindtext}
\renewcommand{\familydefault}{\sfdefault}
\begin{document}

\blindtext

\vspace{1cm}

%\parbox[c][0pt]{\linewidth}{} % When we add this line, the space between both paragraphs increases
X
%.

\vspace{1cm}

\blindtext

\end{document}

然后就更容易看出发生了什么。您有三段文本,其中两段带有 lipsum,一段带有 X。文本行的高度(通常)不取决于行中的特定字符,如果您用 替换,则X字符.较小,但中间段落占用相同的空间。\parbox就像零大小的白色字符一样,因此放置在一行段落中,并占用与任何其他一行段落相同的垂直空间。

值得注意的是,parbox 并不\linwidth宽,它的宽度为零。如果你在里面放置了任何内容,\parbox例如

\parbox[c][0pt]{\linewidth}{.} % 

\linewidth那么你将得到一个溢出的 hbox 警告,因为你有一个宽度缩进\parindent(17pt)的框。

相关内容