Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am trying to understand the sizes of boxes and skips so I decided I wanted to typeset text directly on top of some other text. I don't want to use textpos or anything like that. I am trying to figure out how big of a skip I need to get back to where I was. I would like the green, red and blue boxes to perfectly overlap.

\documentclass{article}
\usepackage{color}

\newbox{\boxA}
\newlength{\skipA}
\savebox{\boxA}{\parbox{\textwidth}{\color{green}Hello\par World}}
\settoheight{\skipA}{\usebox{\boxA}}%

\newbox{\boxB}
\newlength{\skipB}
\savebox{\boxB}{\parbox{\textwidth}{\color{red}Hello\par World}}
\settoheight{\skipB}{\usebox{\boxB}}%
\begin{document}
    \usebox{\boxA}\par\vspace{-\skipA}
    \usebox{\boxB}\par\vspace{-\skipB}
    \parbox{\textwidth}{\color{blue}Hello\par World}
\end{document}

Output showing unaligned text

share|improve this question
add comment

2 Answers

up vote 13 down vote accepted

There are many factors involved here. The main one is the interline glue; Knuth uses the term ‘glue’ to denote the vertical spacings inserted manually or automatically when stacking boxes that are part of paragraphs.

Let's see a simple case first.

\sbox{\boxA}{World}\sbox{\boxB}{World}
\usebox{\boxA}\par
\usebox{\boxB}

The distance between the bottom of the first line to the bottom of the second line will be equal to \baselineskip (12pt is the default value if ten point size is in force). In this case TeX will insert between the two lines a vertical glue equal to the difference between \baselineskip and the height of \boxB.

With a different input such as

\sbox{\boxA}{planet}\sbox{\boxB}{planet}
\usebox{\boxA}\par
\usebox{\boxB}

the glue inserted would be the difference between \baselineskip and the sum of the height of ‘planet’ and the depth (of the previous line). There would be a corrective factor if this difference is less than a threshold (contained in the parameter \lineskiplimit).

So, to get the lines to overlap, you need only to say

\sbox{\boxA}{planet}\sbox{\boxB}{planet}
\usebox{\boxA}\par\vspace{-\baselineskip}
\usebox{\boxB}

because these boxes don't trigger the insertion of the corrective factor.

The case of \sbox{\boxA}{\parbox{\textwidth}{Hello\par World}} is quite different, because TeX treats a \parbox as a unique object whose height is computed in an apparently bizarre way: take the "apparent total height" (that is, how high the box would be if it were sitting on the baseline of the last line inside it) and divide it by two; let's say that x is the length so obtained, while d is the depth of the last line in the \parbox; the height of the box will be x + 2.5pt, the depth x – 2.5pt + d. Thus

\usebox{\boxA}\par\usebox{\boxA}

does trigger the insertion of the corrective factor: the two boxes are stacked one above the other, and TeX inserts \lineskip glue (default 1pt) between them. So, in order to back up exactly you have to sum up the depth of \boxA, its height and \lineskip:

\usebox{\boxA}\par\vspace{-\dp\boxA}\vspace{-\lineskip}\vspace{-\ht\boxA}
\usebox{\boxA}

(it's easier to access directly at the dimensions of the boxes with the low level commands \ht and \dp).

Why that bizarre computation? The answer requires knowing about \vcenter, but it's not really important. Once one knows the height and depth of the involved boxes it's easy to predict the final outcome under normal circumstances.


Where does the 2.5pt comes from? It's not a universal value: this is for Computer Modern fonts at 10pt size. The actual value is the distance from the baseline of the fraction line when one typesets $\frac{1}{2}$. The \vcenter primitive centers a box vertically with respect to this math axis. The height of the math axis is a parameter in the current math symbol font.

share|improve this answer
    
great answer, it makes things a lot clear. Where does the 2.5pt come from in x – 2.5pt + d? –  StrongBad May 28 '12 at 9:59
add comment

To understand boxes you should avoid parbox You example fails because you didn't adjust the parbox. Next you have a interlineskip -- so you need \nointerlineskip

TeXBook page 79:

Exception: No interline glue is inserted before or after a rule box. You can also inhibit interline glue by saying \nointerlineskip between boxes.

To get the height, depth or width of a box you can also use:

\wd\boxname % width of the box
\ht\boxname % height of the box
\dp\boxname % depth of the box

Based on dp you see a box can have a depth.

In the example I only changed the first two boxes.

\documentclass{article}
\usepackage{color}

\newbox{\boxA}
\newlength{\skipA}
\savebox{\boxA}{\parbox[b]{\textwidth}{\color{green}Hello\par World}}
\settoheight{\skipA}{\usebox{\boxA}}%

\newbox{\boxB}
\newlength{\skipB}
\savebox{\boxB}{\parbox[b]{\textwidth}{\color{red}Hello\par World}}
\settoheight{\skipB}{\usebox{\boxB}}%

\fboxsep=0pt
\begin{document}
    \fbox{\usebox{\boxA}}\par\vspace{\dimexpr-\skipA-2\fboxrule\relax}\nointerlineskip
    \fbox{\usebox{\boxB}}
\end{document}
share|improve this answer
    
The b option for parbox is nice. I forgot that a parbox isn't bottom aligned. –  StrongBad May 28 '12 at 10:02
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.