![为什么 `\strut` 在这些场景中有效?](https://linux22.com/image/271163/%E4%B8%BA%E4%BB%80%E4%B9%88%20%60%5Cstrut%60%20%E5%9C%A8%E8%BF%99%E4%BA%9B%E5%9C%BA%E6%99%AF%E4%B8%AD%E6%9C%89%E6%95%88%EF%BC%9F.png)
\strut
似乎是一个强大的命令,可以正确设置行间距;特别是在处理\parbox
s 或minipage
s 格式的文本时。但在 LaTeX 以意外地方。
这里的 MWE 说明了两种情况,即\strut
快速简便地获得正确的行间或文本对齐的方法。
\documentclass{article}
\usepackage[width=7.5in]{geometry}
\usepackage{lipsum}
\pagestyle{empty}
\begin{document}
\noindent
\begin{minipage}[t]{3in}
\hspace*{\fill}Naive Approach\hspace*{\fill}
\vspace{1cm}
\noindent
\begin{tabular}{ll}
first & short text \\
second & \parbox[t]{2.25in}{By putting a long line here I get bad spacing.} \\
third & short text \\
fourth & spacing \\
fifth & short text \\
\end{tabular}
\vspace{1cm}
\leavevmode\vadjust{
\noindent
\raisebox{\dimexpr0.5\totalheight\relax}[0pt][0pt]{\makebox[0pt][r]{Hello}}
}%
\lipsum[1]
\vspace{1cm}
On this side of things, the placement of \verb-Hello- just isn't easily
gotten correct whether I substitute
\vspace{0.5cm}
\centering
\verb|\dimexpr0.5\totalheight\relax|
by
\verb|\depth| or just plain \verb|0pt|.
\vspace{0.5cm}
\textbf{Note:} if I replace \verb-Hello- by \verb-Why- and then raise
the box by \verb-\depth- then things appear to be visually aligned correctly.
\end{minipage}\hspace*{\fill}%
\begin{minipage}[t]{3in}
\hspace*{\fill}Better spacing with \verb=\strut=\hspace*{\fill}
\vspace{1cm}
\noindent
\begin{tabular}{ll}
first & short text \\
second & \parbox[t]{2.25in}{By putting a long line here I get bad spacing.\strut} \\
third & short text \\
fourth & spacing \\
fifth & short text \\
\end{tabular}
\vspace{1cm}
\leavevmode\strut\vadjust{
\noindent
\raisebox{\dp\strutbox}[0pt][0pt]{\makebox[0pt][r]{Hello}}
}%
\lipsum[1]
\end{minipage}
\end{document}
我已经看到了以下帖子的答案\strut、\mathstrut 和 \vphantom 之间有什么区别?和包含 parbox 的项目之间的间距。它们有助于理解何时使用\strut
。我已经了解了 的\strut
定义。但我仍然不清楚它\strut
究竟是如何完成任务的。
有人能花点时间解释一下如何使用\strut
才能达到正确的效果吗?或者给我指出正确的方向?
笔记 我也见过这个解释但除了重申定义之外,我仍然不清楚为什么它在上述情况下起作用。
更新
在考虑了 @Werner 提供的示例(使用\fbox
s 来显示 所创建的深度)之后\strut
,我决定尝试一些类似的东西来说明涉及 的情况\vstrut
。不幸的是,这并不像将我的示例放入 中那么简单\fbox
。基本上内容消失了。但我坚持了下来。在下面的 MWE 中,我测试了三种不同的场景,每种场景都有三种情况。
\documentclass{article}
\newcommand{\aestrut}{\raisebox{0pt}[0pt][0pt]{\rule[\dimexpr-0.3\baselineskip\relax]{0.4pt}{\dimexpr\baselineskip\relax}}}
\newcommand{\visibleStrutAndBaseline}{\aestrut\rule[-0.4pt]{1cm}{0.4pt} Followed by text}
\newcommand{\aehline}{\rule[-0.4pt]{1cm}{0.4pt}}
\newcommand{\aecontent}[1]{\aehline\hspace{\dimexpr-1cm+0.25em}#1}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\begin{document}
\visibleStrutAndBaseline --- using No strut
{\leavevmode\vadjust{\raisebox{0pt}[0pt][0pt]{\aecontent{Text}}}}
\vspace{0.25cm}
\visibleStrutAndBaseline --- using Strut but not raised
{\leavevmode\strut\vadjust{\raisebox{0pt}[0pt][0pt]{\aecontent{Text}}}}
\vspace{0.25cm}
\visibleStrutAndBaseline --- using Strut and raised by depth of strut
{\leavevmode\strut\vadjust{\raisebox{\dp\strutbox}[0pt][0pt]{\aecontent{Text}}}}
%%--------------------------------------------------------------------------------
\vspace{1cm}
\visibleStrutAndBaseline --- using No strut
{\leavevmode\vadjust{\raisebox{0pt}[0pt][0pt]{\aecontent{Ziggy}}}}
\vspace{0.25cm}
\visibleStrutAndBaseline --- using Strut but not raised
{\leavevmode\strut\vadjust{\raisebox{0pt}[0pt][0pt]{\aecontent{Ziggy}}}}
\vspace{0.25cm}
\visibleStrutAndBaseline --- using Strut and raised by depth of strut
{\leavevmode\strut\vadjust{\raisebox{\dp\strutbox}[0pt][0pt]{\aecontent{Ziggy}}}}
%%--------------------------------------------------------------------------------
\vspace{1cm}
\visibleStrutAndBaseline\rule[-2ex]{2pt}{3ex} --- using No strut
{\leavevmode\vadjust{\raisebox{0pt}[0pt][0pt]{\aecontent{Deep}}}}
\vspace{0.25cm}
\visibleStrutAndBaseline\rule[-2ex]{2pt}{3ex} --- using Strut but not raised
{\leavevmode\strut\vadjust{\raisebox{0pt}[0pt][0pt]{\aecontent{Deep}}}}
\vspace{0.25cm}
\visibleStrutAndBaseline\rule[-2ex]{2pt}{3ex} --- using Strut and raised by depth of strut
{\leavevmode\strut\vadjust{\raisebox{\dp\strutbox}[0pt][0pt]{\aecontent{Deep}}}}
\end{document}
场景涉及文本主线的深度和文本的深度\vadjust
。因此,在场景一内容的深度\vadjust
是零。 在场景二这一内容具有非同寻常的深度。在第三种情况我创建了一个深的深度。
对于每个场景,有三种情况:案例一是考虑当\strut
不使用时会发生什么。 案例二是使用\strut
但不提高的内容\vadjust
。而第三种情况说明了通过深度提高内容\strut
。
在所有场景和案例我使用可见的支柱来模仿 \strut
,我将其高度和深度设置为零,以免无意中扰乱垂直间距。
这个例子让我明白了两件事: 第一的文本究竟放在哪里\vadjust
:当然,其他人说它放在了行间。这当然是真的。@DavidCarlisle 更正:它似乎被放置了,以便顶部 的\vadjust
内容与底部\vadjust
(不是底线)是判罚点球的界线。第二我能看到的是,只要正文没有任何带有荒野深度,\strut
则将足够深以影响正确的深度以获得所需的对齐。
答案1
从其他答案的评论来看,你似乎想专注于
\leavevmode\strut\vadjust{%
\noindent
\raisebox{\dp\strutbox}[0pt][0pt]{\makebox[0pt][r]{Hello}}
}%
第一个\leavevmode
并不是真正需要的,因为\strut
定义为进入水平模式,但它没有坏处,而且更清楚地表明代码需要水平模式。接下来是\strut
这很重要,我们会回到这一点。然后:立即评估\vadjust
的内容(如),但生成的垂直材料不会被装箱,而是插入到稍后将根据段落中的行构建的垂直列表中。\vadjust
\vbox
代码的目的是使其hello
与前一个框的基线对齐,但 vadjust 材料直接插入到列表中,而不是强制基线间距,因此要与前一个框的基线对齐,您需要备份前一个框的深度。“前一个框”尚未构建,它由以 vadjust 节点结尾的行中的任何文本组成,如果该行有任意文本,则其深度将未知。但是,由于\strut
已添加并且其深度比任何字母或其他普通文本都大,因此可以合理地假设该行的深度是 strutbox 的深度。
这样\raisebox{\dp\strutbox}
就回到了上一行的基线。
如果您在行中放置一些深度内联数学或内联表格,这将会失败,但如果您需要处理这个问题,您需要一个更复杂的两遍测量方案。
答案2
这里的主要问题与内容相关的边界框有关。有些元素的深度与其他元素不同,最明显的是文本没有下降部分。例如,Hello
没有深度,而spacing
有一些深度。背后的想法\strut
是确保\strut Hello
和\strut spacing
(例如)垂直覆盖相同的地面。
当你查看此 MWE 时,可以看到一个简单的示例:
\documentclass{article}
\newcommand{\ddd}[1]{\fbox{\strut#1}\,\fbox{#1}}% Show the difference in bounding boxes
\setlength{\fboxsep}{-\fboxrule}% For this example
\begin{document}
Letters: \ddd{a}\ \ddd{b}\ \ddd{p} \ddd{Q}
\bigskip
Words: \ddd{Hello}\ \ddd{spacing}
\end{document}
可以看出,这些字母/单词的边界框在垂直方向上是等同的,即使它们各自可能具有不同的下降部/上升部。更具体地说,在现行字体中,\strut
确保高度至少为 70% \baselineskip
,深度至少为 30% 。根据的定义(由\baselineskip
\strutbox
\strut
),在LaTeX 内核作为...的一部分\set@fontsize
:
\setbox\strutbox\hbox{%
\vrule\@height.7\baselineskip
\@depth.3\baselineskip
\@width\z@}%
因此,具体到您的情况,您可以看到内部\strut
增加\parbox
了框的深度,因此从一行跳到下一行(参见与spacing
上面相关的边界框的差异)。
在您的特定情况下,第二次比较Hello
有点奇怪。在第一个比较中,您根据高度+深度(或\totalheight
)来提高它,而在第二个比较中,您仅根据深度来提高它(\dp
)。由于Hello
具有高度,因此第一次提高不为零,而在第二次比较中,由于Hello
具有零深度,因此提高为零。
答案3
首先,它\strut
做什么?它只是生成一个不可见的规则,其高度为当前基线跳跃的 70%,深度为 30%。
A\parbox[t]
使框的高度与其第一行一样高;所有后续行都会影响其深度。因此,当\parbox[t]
找到 a 时,在它所在的行和下一行之间\lineskip
会插入粘连(除了单行的情况\parbox[t]
)。因此,获得均匀间距的修复方法是以 结尾\parbox[t]
并\strut
在下一行添加一个。这将确保(除了行太高或太深的情况)基线是分开的(利用粘连通常为零的\baselineskip
事实)。\lineskip
这在您的第一个示例中显示,其中\parbox
嵌套在 a 中tabular
。无需\strut
在下一行中添加 a ,因为 a 中的行tabular
彼此之间完全由 struts 隔开。
第二个示例更加扭曲。 中的材料\vadjust
应该是垂直材料而不是水平材料,这导致水平模式启动。 材料被添加之间行,并且由于它包含一个框,它将贡献其高度和深度(但没有行间粘连)。您可以通过\vadjust{Hello}
改为说来检查这一点。因此它不能很好地说明\strut
用法。
答案4
\strut
创建一个不可见的 vbox,使其填充基线之间的空间。因此(在典型情况下)间距是均匀的。