Why is `\strut` working in these scenarios?
The main issue here deals with the bounding boxes associated with the contents. Some elements have different depths than others, most notably from text without descenders. For example, Hello
has no depth, while spacing
has some. The idea behind \strut
is to ensure that \strut Hello
and \strut spacing
(for example) cover the same ground vertically.
A quick example of this is visible when you view this 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}
Is can be seen, the bounding boxes of these letters/words are vertically equivalent to one another, even though they each may have different descenders/ascenders. More specifically, \strut
ensures at least a 70% \baselineskip
in terms of height, and 30% \baselineskip
in depth in the prevailing font. From \strutbox
's definition (used by \strut
) in the LaTeX kernel as part of \set@fontsize
:
\setbox\strutbox\hbox{%
\vrule\@height.7\baselineskip
\@depth.3\baselineskip
\@width\z@}%
So, specific to your case, you can see that the \strut
inside the \parbox
increases the depth of the box, and therefore the skip from one line to the next (see the difference in the bounding boxes related to spacing
above).
The second comparison to Hello
is somewhat bizarre in your particular case. In the first you raise it based on height+depth (or \totalheight
) while in the second you raise it based on depth only (\dp
). Since Hello
has height, the first raise is non-zero, while it is zero in the second, since Hello
has zero depth.
Also see, as reference, How to keep a constant \baselineskip
when using minipage
s (or \parbox
es)?
From the comments on the on the other answers, it seems like you want to concentrate on
\leavevmode\strut\vadjust{%
\noindent
\raisebox{\dp\strutbox}[0pt][0pt]{\makebox[0pt][r]{Hello}}
}%
The first \leavevmode
isn't really needed as \strut
is defined to get into horizontal mode, however it does no harm and makes it clearer that the code needs horizontal mode.
Then comes the \strut
this is important and we'll come back to that.
Then \vadjust
: the content of \vadjust
is evaluated immediately (like \vbox
) but the resulting vertical material is not boxed but inserted into the vertical list that will be later constructed from the lines in the paragraph.
The intention of the code is to make hello
aligned to the baseline of the previous box, but the vadjust material is inserted directly into the list not forced to baseline spacing so to align to the baseline of the previous box you need to back up by the depth of the previous box. the "previous box" has not yet been constructed, it consists of whatever text ends on the line that has the vadjust node If that line had arbitrary text its depth would not be known. However as \strut
was added and this had bigger depth than any letter or other normal text it is reasonable to assume the depth of the line is the depth of strutbox.
So \raisebox{\dp\strutbox}
gets you back to the baseline of the previous line.
This will fail if you put some deep inline math or an inline tabular in the line, but if you need to deal with that you need a more complicated two pass measuring scheme.
First of all, what does \strut
do? It simply produces an invisible rule whose height is 70% and the depth 30% of the current baselineskip.
A \parbox[t]
makes a box as high as its first line; all the successive lines contribute to the depth. Thus, when a \parbox[t]
is found, between the line in which it is and the next one, the \lineskip
glue will be inserted (excluding the trivial case of a one line \parbox[t]
). A fix for getting uniform spacing is thus to end the \parbox[t]
with \strut
and adding one in the next line. This will ensure (except in the case where lines are too high or deep) that the baselines are \baselineskip
apart (using the fact that the \lineskip
glue is usually zero).
This is shown in your first example, with the \parbox
nested in a tabular
. There's no need to add a \strut
in the following row, because rows in a tabular
are kept apart from each other exactly by struts.
The second example is more contorted. The material in \vadjust
should be vertical material and not horizontal material, which causes however horizontal mode to start. The material is added between lines and, since it contains a box, it will contribute its height and depth (but no interline glue). You can check this by saying \vadjust{Hello}
instead. So it doesn't provide a good illustration of \strut
usage.