为什么 `\strut` 在这些场景中有效?

为什么 `\strut` 在这些场景中有效?

\strut似乎是一个强大的命令,可以正确设置行间距;特别是在处理\parboxs 或minipages 格式的文本时。但在 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 提供的示例(使用\fboxs 来显示 所创建的深度)之后\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具有零深度,因此提高为零。

另请参阅,作为参考,\baselineskip使用minipages (或es) 时如何保持常数\parbox

答案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,使其填充基线之间的空间。因此(在典型情况下)间距是均匀的。

相关内容