解释

解释

我想将两个小页面整合到文本中,保持行距不变。使用该\begin{minipage}[t]选项,小页面上方的空间是正确的(绿色圆圈)。但不幸的是,下方的空间太短了(红色圆圈)。我该如何将其调整为“正常基线跳跃”?

在此处输入图片描述

梅威瑟:

\documentclass[a4paper,DIV=15,oneside,12pt]{scrartcl}
\usepackage[english]{babel} 
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc} 
\usepackage{blindtext}
\usepackage{setspace}
\usepackage{enumitem}

\parskip 0pt
\parindent 0pt

\begin{document}
\pagestyle{empty}
\onehalfspacing

\blindtext\par
\begin{minipage}[t]{0.6\textwidth}
\blindtext
\end{minipage}\hfill
%Minipage 2
\begin{minipage}[t]{0.37\textwidth}
%\centering\rule{3cm}{2cm}
\begin{enumerate}[leftmargin=*,label=\alph{*}),itemsep=0pt,partopsep=0pt,topsep=0pt, parsep=0pt]
\item Test 1
\item Test 2
\end{enumerate}
\end{minipage}\par
\blindtext
\end{document}   

答案1

您的问题的解释相当复杂。如果您愿意,可以直接跳到下面的解决方案。

解释

TeX 排版段落时,其行为大致如下:首先将段落分成几行(使用带有多个参数的复杂算法)。这些行被放入水平框(或\hbox)中,然后框被放在主垂直列表中。主垂直列表包含创建页面所需的所有材料。

TeX 会尝试确保垂直列表中连续的水平框之间的间隔使得每个框的基线分开\baselineskip。我们可以使用 TeX 来实际查看这一点。

以下是一些普通的 TeX(使用tex或编译pdftex

\showboxdepth=1
\showboxbreadth=10000
\tracingonline=1

\setbox0=\vbox{
First line\hfil\break
Second line
}
\showbox0
\end

编译后,它会打印出里面的内容\vbox,其中段落被分成两行。参数\boxshow...控制 TeX 如何打印框的内容。以下是输出。

> \box0=
\vbox(18.94444+0.0)x469.75499
.\hbox(6.94444+0.0)x469.75499, glue set 409.81047fil []
.\penalty 300
.\glue(\baselineskip) 5.05556
.\hbox(6.94444+0.0)x469.75499, glue set 420.31046fil []

乍一看,这个可能有点复杂,但它告诉我们的是,这\box0是一个\vbox高度为 18.94444pt、深度为 0pt、宽度为 469.75499pt 的 。也就是(height+depth)xwidth。在里面我们可以看到两个\hboxes,分别对应段落的两行。在它们之间,有一个 ,\glue它对应于\baselineskip。请注意,顶部框的深度加上粘连加上底部框的高度是 12pt,也就是\baselineskip

现在 TeX 也不希望连续的框靠得太近,以防止它们重叠。为了防止这种情况,当框靠得太近时,TeX 会在框之间插入一些空间。确切的算法在这里并不重要,但关键是我们可以使用 来禁用此行为\nointerlineskip

现在你可能想知道两个文本框怎么会靠得太近。如果你有一个有深度的框,就会发生这种情况在具有高度的盒子顶部n使得+n> \baselineskip

那么所有这些和你的问题有什么关系呢?好吧,TeX 有三种类型的垂直框,\vbox\vtop\vcenter。我们先忽略它,\vcenter因为它有点奇怪。\vbox\vtop的不同之处在于它们放置它们的位置参照点— 即与它们的基线相对应的点。A\vbox将其参考点设置为列表中最后一个框的参考点(即,通常是框中段落最后一行的基线)。相反,a\vtop将其参考点设置为列表中第一个框的参考点(即,段落顶行的基线)。

我们可以看到实际效果。

\noindent
\vbox{
    \hsize=1in
    Top line\hfill\break
    Bottom line
}
\vtop{
    \hsize=1in
    Top line\hfill\break
    Bottom line
}
\end

在此处输入图片描述

您可以看到左侧框的底线如何与右侧框的顶线对齐。

我们可以像以前一样打印出这两个框的样子。

左边的框:

\vbox(18.94444+0.0)x72.26999
.\hbox(6.94444+1.94444)x72.26999, glue set 16.4366fill []
.\penalty 300
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x72.26999, glue set 20.18652fil []

正确的框:

\vbox(6.94444+12.0)x72.26999
.\hbox(6.94444+1.94444)x72.26999, glue set 16.4366fill []
.\penalty 300
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x72.26999, glue set 20.18652fil []

主要区别在于这两个框的高度和深度(每个列表的顶行)。

这导致了一个棘手的问题。如果我们使用,\vtop并且页面上的下一行只是段落中的一行,会发生什么?让我们来看看。

\parindent=0pt
\leavevmode
\vtop{
    \hsize=1in
    Top line\hfill\break
    g Bottom line
}

Next line
\end

在此处输入图片描述

我取消了缩进,并在第二行以 a 开头,g因为它低于基线。让我们看看构造的框。(我将所有内容包裹在 a 中\vbox并用于\showbox查看输出。因此,下面有一个额外的外部 vbox。我增加了\showboxdepth1 以查看下一个内部框。)

\vbox(28.83333+0.0)x469.75499
.\vbox(6.94444+13.94444)x72.26999
..\hbox(6.94444+1.94444)x72.26999, glue set 36.4366fill []
..\penalty 300
..\glue(\baselineskip) 3.11111
..\hbox(6.94444+1.94444)x72.26999, glue set 11.85318fil []
.\glue(\parskip) 0.0 plus 1.0
.\glue(\lineskip) 1.0
.\hbox(6.94444+0.0)x469.75499, glue set 429.75491fil
..\hbox(0.0+0.0)x0.0
..\tenrm N
..\tenrm e
..\tenrm x
..\tenrm t
..\glue 3.33333 plus 1.66666 minus 1.11111
..\tenrm l
..\tenrm i
..\tenrm n
..\tenrm e
..\penalty 10000
..\glue(\parfillskip) 0.0 plus 1.0fil
..\glue(\rightskip) 0.0

这里有几点需要注意:

  1. 第二个\vbox对应于我们的\vtop
  2. \parskip段落之间插入了A ;并且
  3. 在和 后面包含 的\baselineskip之间插入了没有。取而代之的是。 的原因是 的深度和 后面的高度大于。如果 TeX 试图将它们的基线分开,它们就会重叠。\vtop\hboxNext line\lineskip\lineskip\vtop\hbox\baselineskip\baselineskip

也许现在您可以用自己的代码看到这个问题了。minipage带有[t]选项的 会产生一个\vtop。因此,TeX 无法确保 中底线的基线minipage远离\baselineskip下一行的基线。相反,它会插入\lineskip远远不够的空间。

您可能会认为解决方案是将 切换为minipage[b]但随后您会遇到与上面类似的情况。

解决方案

处理此问题的正常方法是\strut在 的最后一行中放置一个\vtop,关闭行间跳过(即抑制粘合),并在下一段的第一行中\lineskip放置一个。\strut

A\strut插入一个盒子(即\box\strutbox),其高度 + 深度通常等于\baselineskip。但是,这在你的情况下不起作用。原因是\onehalfspacing改变了\baselineskip但没有触及\box\strutbox

因此,我们需要做的是用\vskip适当长度的结束较长的框,关闭行间跳过,并使用\strut。那么合适的长度是多少?好吧,我们想要\baselineskip=(高度\box\strutbox)+(最后一个框的深度\vbox)+(我们的显式\vskip)。

我们可以通过设置一个临时\skip寄存器(我选择0)来计算\baselineskip- \ht\strutbox-\prevdepth其中\prevdepth是垂直列表上最后一个框的深度(即最后一行文本)。

最后两点警告。

  1. 这不适用于minipage,我没有调查原因。
  2. enumerate通常会在其上方添加空格。这被minipage执行的所抑制\@setminipage。我理解它的\@setminipage工作原理,但我不明白如何仅使用enumitem的选项来阻止这种行为。因此,此代码改为执行\@setminipage

这是完整的代码。

\documentclass[a4paper,DIV=15,oneside,12pt]{scrartcl}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{blindtext}
\usepackage{setspace}
\usepackage{enumitem}

\parskip 0pt
\parindent 0pt

\begin{document}
\pagestyle{empty}
\onehalfspacing

\blindtext\par
\noindent
\parbox[t]{0.6\textwidth}{
\blindtext

\skip0=\baselineskip
\advance\skip0 by-\prevdepth
\advance\skip0 by-\ht\strutbox\relax
\vskip\skip0
}\hfill
\parbox[t]{0.37\textwidth}{
\csname @setminipage\endcsname
\begin{enumerate}[leftmargin=*,label=\alph{*}),itemsep=0pt,partopsep=0pt,topsep=0pt, parsep=0pt]
\item Test 1
\item Test 2
\end{enumerate}
}
\par
\nointerlineskip
\strut\blindtext
\end{document}

在此处输入图片描述

相关内容