2

I am trying to get my columns to line up on a grid, a task which is sometimes tricky in LaTeX. (See this article for some tips I'm using.)

Everything is working great except this one situation: at the end of my tabularx environment, TeX is skipping slightly less space than it ought to. Notice how the lines are perfectly aligned until the end of the tabular environment in number 9006, and then a couple of points too high for the remainder of the page:

enter image description here

From my reading of the code, it ought to be inserting a \par for the empty line, which skips 0pt, then skipping 1\baselineskip of vertical space at the start of the \itemheading, resulting in an integral multiple of \baselineskip vertical space. That's what's happening for the paragraphs that aren't adjacent to tabular environments.

I'm sure that there is some length (\aftertabularxskip?) that I have failed to set, but I cannot for the life of me find any information on how vertical spacing works before and after a tabular environment, except that tables are treated as boxes, which doesn't help much because it still doesn't explain how the box is sized.

Code for example above (my actual document has a much cleaner set of macros, but I inlined almost all of them for this example to rule out issues with the macros):

% I'm using memoir for this document, but the same issue occurs if
% using the book class and the tabularx package
\documentclass[openany, letter]{memoir}

\usepackage[utf8]{inputenc}
\usepackage{mathpazo}

% the following three lines don't change the problem, it's just easier to see the issue when the page is formatted
\usepackage[inner=1.3in, outer=1.2in, top=54pt, bottom=71pt, columnsep=12pt, headsep=10pt, headheight=12pt, marginparwidth=0.6in, marginparsep=0.2in, heightrounded=true]{geometry}
\usepackage[colaction]{multicol}
\setlength\columnseprule{0.5pt}

\renewcommand\bigskip{\vspace{1\baselineskip}}
\lineskip=0pt
\lineskiplimit=-10pt
\topskip=1\baselineskip
\setlength{\parskip}{0.0pt}
\setlength{\parindent}{15pt}

\newcommand\itemheading[1]{\vspace*{1\baselineskip}\noindent\textbf{#1}\enspace}
\usepackage{lipsum}

\begin{document}
\begin{multicols}{2}

\itemheading{9000}%
\lipsum[1]

\itemheading{9001}%
\lipsum[2]

\itemheading{9002}%
\lipsum[3]

\itemheading{9003}%
\lipsum[4]

\itemheading{9006}\bigskip

\noindent \begin{tabularx}{\linewidth}{r >{\raggedright\arraybackslash}X}
    %\setlength{\extrarowheight}{0pt}
    %\setlength{\extratabsurround}{0pt}
    %\setlength{\aboverulesep}{0pt}
    %\setlength{\belowrulesep}{0pt}
    \emph{X}: & ``This is some test text.''\\
    \emph{Y}: & ``This is some more test text.''\\
    \emph{Z}: & ``This is even more test text.''\\
\end{tabularx}

\itemheading{9007}%
\lipsum[5]

\end{multicols}
\end{document}

Edit: If it's helpful, I made an interesting discovery: the problem does not occur if only one or two lines are present in the tabularx environment. It occurs with three or more, and the error is different depending on how many lines there are. And with four or more, an incorrect amount of space is inserted at the top, too.

  • tabularx, like tabular is an inline horizontal box and has no spacing rules attached to it at all, it is just positioned like a big letter – David Carlisle May 7 '18 at 1:24
  • if you add \showoutput you will see that you are getting \lineskip rather than \baselineskip spacing which always loses grid allignment. – David Carlisle May 7 '18 at 1:35
  • @DavidCarlisle I'm not sure what you mean by “you are getting \lineskip spacing” – there are \lineskip's in the output, but they are all 0 (because I set it to 0 in the preamble). – scorchgeek May 7 '18 at 1:57
  • (This said, I will happily admit I don't really understand vertical mode very well!) – scorchgeek May 7 '18 at 2:37
  • they are 0 because you set \lineskip to 0pt but the fact that they are used means that tex can not maintain baselineskip spacing (as that is the only time lineskip is used) note a tabular is vertically centered so has large height and depth – David Carlisle May 7 '18 at 7:49
2

TeX keeps lines at constant distance by inserting a glue. If you do e.g.

\documentclass{article}

\parindent=0pt
\begin{document}
\showoutput
aa\\aa\\AA\\..
\end{document}

you will see in the log lines like this:

\glue(\baselineskip) 7.69446
\glue(\baselineskip) 5.16669
\glue(\baselineskip) 10.94446

The glue value differ depending on the height and depth of the adjoining lines: the first ist between aa and aa, the second between aa and AA and the third between A and the dots ..

If you separate the lines with \par the same happens: TeX inserts this glue so that you get uniformed spacing here too:

\documentclass{article}

\parindent=0pt
\parskip=10pt
\begin{document}
\showoutput
aa\par aa\par AA\par ..
\end{document}

When you insert a large object whose height or depth exceeds the default height/depth of a line (and your tabularx is such a large object) this glue is no longer inserted but the fix \lineskip is used instead. This means that the height and depth of the adjoining lines is not longer taken into account: if they contain only dots they will be nearer to the large object as in the case where you have an Aj in it.

So to get alignment again I suggest to

  1. use [t] alignment for the tabular (to reduce the problem only to the bottom)
  2. Use a strut in the following heading to enforce a normal line height.

The tikz line shows the effect:

\documentclass[openany, letter]{memoir}

\usepackage[utf8]{inputenc}
\usepackage{mathpazo}
\usepackage{tikz}
% the following three lines don't change the problem, it's just easier to see the issue when the page is formatted
\usepackage[inner=1.3in, outer=1.2in, top=54pt, bottom=71pt, columnsep=12pt, headsep=10pt, headheight=12pt, marginparwidth=0.6in, marginparsep=0.2in, heightrounded=true]{geometry}
\usepackage[colaction]{multicol}
\setlength\columnseprule{0.5pt}

\renewcommand\bigskip{\vspace{1\baselineskip}}
\lineskip=0pt
\lineskiplimit=-10pt
\topskip=1\baselineskip
\setlength{\parskip}{0.0pt}
\setlength{\parindent}{15pt}

\newcommand\itemheading[1]{\vspace*{1\baselineskip}\noindent\textbf{\strut #1}\enspace}
\usepackage{lipsum}

\begin{document}
\begin{multicols}{2}

\itemheading{9000}%
\lipsum[1]

\itemheading{9001}%
\lipsum[2]

\itemheading{9002}%
\lipsum[3]

\itemheading{9003}%
\lipsum[4]

\itemheading{9006}\bigskip

\noindent \begin{tabularx}{\linewidth}[t]{r >{\raggedright\arraybackslash}X}
    %\setlength{\extrarowheight}{0pt}
    %\setlength{\extratabsurround}{0pt}
    %\setlength{\aboverulesep}{0pt}
    %\setlength{\belowrulesep}{0pt}
    \emph{X}: & ``This is some test text.''\\
    \emph{Y}: & ``This is some more test text.''\\
    \emph{Z}: & ``This is even more test text.''\\
\end{tabularx}

\itemheading{\tikz[overlay]\draw[red](0,0)--++(-10cm,0);9007}%
\lipsum[5]

\end{multicols}
\end{document}

enter image description here

  • Thank you so much! I've been beating my head against the wall here. I was able to figure out that [t] fixed the top alignment, but I didn't know about \strut. For future reference, you can read about vboxes and strut on page 82 of The TeXBook. – scorchgeek May 8 '18 at 22:17
  • I'll have to play around a bit more to get everything to work since my actual document is considerably more complex than the sample with respect to the locations where these tabular environments can appear, but \strut was the missing piece and I should be able to take it from here. – scorchgeek May 8 '18 at 22:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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