[Tex/LaTex] Changes in spacing (“Spacing” environment) for a block should not affect the line spacing of the block to the material above and below

line-spacingmemoir

When I use memoir with \OnehalfSpacing and I temporarily set things within \begin{Spacing}{1}[...]\end{Spacing} (\SingleSpacing for some reason leads to looser spacing elsewhere in my document), I get uneven line spacing:

\documentclass{memoir}
\usepackage{lipsum}

\OnehalfSpacing
\raggedbottom


\begin{document}

\lipsum[1] Before the block \dots
\par\nopagebreak\vspace{0.25\baselineskip}\nopagebreak % not sure whether two occurrences of \nopagebreak are needed
\begin{Spacing}{1}
  \begin{tabular}{ll}
    foo & bar \\
    baz & qux \\
  \end{tabular}
\end{Spacing}
\par\vspace{0.5\baselineskip}
\noindent \ldots{} after the block.

\lipsum[1] Before the block \ldots
\par\nopagebreak\vspace{0.25\baselineskip}\nopagebreak % not sure whether two occurrences of \nopagebreak are needed
\begin{Spacing}{1}
\noindent
\hspace*{1cm} foo \\
\hspace*{1cm} bar \\
\hspace*{1cm} baz
\end{Spacing}
\par\vspace{0.2\baselineskip}
\noindent \ldots{} after the block.


\newpage


\lipsum[1] Before the block \dots
\begin{Spacing}{1}
  \begin{tabular}{ll}
    foo & bar \\
    baz & qux \\
  \end{tabular}
\end{Spacing}
\noindent \ldots{} after the block.

\lipsum[1] Before the block \ldots
\begin{Spacing}{1}
\noindent
\hspace*{1cm} foo \\
\hspace*{1cm} bar \\
\hspace*{1cm} baz
\end{Spacing}
\noindent \ldots{} after the block.

\end{document}

Page 1 uses \vspace commands with manually set arguments to correct for the uneven spacing (my values are visual guesses). Page 2 has the same content but shows the result if those 4 lines are omitted; this is what I mean by "uneven". My usage of \par is inspired by this question about the same issue on the paragraph level; it might not be necessary.

What I want is line spacing that is evenly 1.5-spaced up to the first line of the 1-spaced content and that is evenly 1.5-spaced starting with the last line of the 1-spaced content. That is, the spacing between the "foo"-line and the line above (in both instances) and between the "baz"-line and the line below (in both instances) should show ordinary 1.5-spacing, like the "lorem ipsum" paragraphs. Is there an easy way to achieve such even spacing? Note my use of \raggedbottom. There should be no distinction whether the embedded material "belongs to the previous paragraph" or not. ("LaTeX goes to a lot of effort to distinguish in-paragraph lists from end- or start-of-paragraph lists"; comment (quoted approximately) by David Carlisle)

Best Answer

The following does what is wanted, for tabulars. It uses the fact that tabular line spacing is determined by \strutbox whose height and depth in the memoir class are defined to be respectively .7 and .3 of the current \baselineskip.

Actually, this is the same as in the article class. Anyhow using \strutbox in the code is better, so I updated accordingly the answer. And the code now also takes into account \arraystretch (changes to \arraystretch should happen before the \MySpacing environment).

The included output has examples on two columns.

Last edit: new version of the helper macro \AfterMySpacing, which deals better with a page break occuring exactly after the end of the \MySpacing environment.

Added explanations: this document (with memoir class) starts in \OnehalfSpacing mode (this is a macro of memoir which enlarges the \baselineskip by a value depending on the type size, for 10pt the factor is 1.25). Then the column on the right switches to \DoubleSpacing (this does not mean that the interline spacing is doubled, the ratio is rather 1.667 for 10pt size).

The boxed values are the parameters given to the \MySpacing environment. This parameter tells the environment which multiple of the standard baselineskip (whose value is set up by the class depending on the font size option passed to it) to use for interline spacing in the tabular environment (recall that tabulars add \struts to ensure regular line spacing -- a safeguard which fails if a cell contents has a height or depth larger than the used strut). This multiplier is applied to the default \baselineskip, not to the one used in the surrounding paragraph already stretched out either by \OnehalfSpacing or \DoubleSpacing.

Finally, there is a LaTeX parameter called \arraystretch, normally set to 1, which multiplies the interline-spacing of all tabulars and arrays. The environment \MySpacing was written to take it into account. So the examples end with a test of this by setting the \arraystretch to 2 but using parameter .5 so that the net effect is like using \MySpacing with parameter 1.

Note 1: with the parameter given to \MySpacing set to only .75, the strut used in the tabular has (with the default fonts) its height a tiny bit smaller than the height of the letter X (circa half a point smaller), hence the line spacing is not exactly as intended (and can be irregular inside the tabular, depending on its content), although this is not so visible to the naked eye. But this problem goes away for parameter values higher than .82.

Note 2: if the environment \MySpacing contains, rather than a tabular, text in lines (ending with \\ except the last one), the wished-for spacing with respect to the surrounding lines will be obtained by inserting a \strut in both the first and the last lines of the enclosed block. (assuming \arraystretch equal to 1).

\documentclass{memoir}
\usepackage{multicol}

\OnehalfSpacing
\raggedbottom

\makeatletter

% helper macro for the environment MySpacing 
% initial version:
%\newcommand{\AfterMySpacing}{\noindent
%       \vphantom{\vrule height \baselineskip depth \z@}}

% new method, better if pagebreak occurs right after the MySpacing block
\newcommand{\AfterMySpacing}{%
   \vskip\dp\strutbox
   \prevdepth\dp\strutbox
   \noindent\strut}  % <- the  \strut here could be removed, TeX adds the 
                     % necessary vertical skip.
                     % And, actually, perhaps the macro would be more flexible
                     % also with the ending \noindent removed.

\newenvironment{MySpacing}[1]
      {\par\nointerlineskip
        \vskip\baselineskip
        \def\baselinestretch{#1}\@currsize
        \vskip-\arraystretch\ht\strutbox\relax % replaces \vskip-.7\baselineskip
      }
      {\par\nointerlineskip
       \vskip-\arraystretch\dp\strutbox\relax  % replaces \vskip-.3\baselineskip
       \ignorespacesafterend\aftergroup\AfterMySpacing}
\makeatother

\begin{document}

\begin{multicols}{2}
  \fbox{2} Before the block Before the block Before the block\dots
  \begin{MySpacing}{2}
    \hspace*{1cm}%
    \begin{tabular}{ll}
      ooo & xxx \\
      baz & qux \\
      foo & pqr \\
    \end{tabular}
  \end{MySpacing}
  \ldots{} after the block after the block after the block after the block 
  after the block

  \fbox{1} Before the block Before the block Before the block\dots
  \begin{MySpacing}{1}
    \hspace*{1cm}%
    \begin{tabular}{ll}
      ooo & XXX \\
      baz & qux \\
      foo & abc \\
    \end{tabular}
  \end{MySpacing}
  \ldots{} after the block after the block after the block after the block
  after the block

  \fbox{.75} Before the block Before the block Before the block\dots
  \begin{MySpacing}{.75}
    \hspace*{1cm}%
    \begin{tabular}{ll}
      ooo & XXX \\
      baz & qux \\
      foo & pqr \\
    \end{tabular}
  \end{MySpacing}
  \ldots{} after the block after the block after the block after the block 
  after the block

\columnbreak

  \DoubleSpacing

  \verb|\DoubleSpacing|

  \fbox{2} Before the block Before the block Before the block\dots
  \begin{MySpacing}{2}
    \hspace*{1cm}%
    \begin{tabular}{ll}
      ooo & XXX \\
      baz & qux \\
      foo & pqr \\
    \end{tabular}
  \end{MySpacing}
  \ldots{} after the block after the block after the block after the block 
  after the block

  \renewcommand{\arraystretch}{2}

  \verb|\renewcommand{\arraystretch}{2}|
  % for testing purposes

  \fbox{.5} Before the block Before the block Before the block\dots
  \begin{MySpacing}{.5}
    \hspace*{1cm}%
    \begin{tabular}{ll}
      ooo & XXX \\
      baz & qux \\
      foo & pqr \\
    \end{tabular}
  \end{MySpacing}
  \ldots{} after the block after the block after the block after the block 
  after the block

\end{multicols}

\end{document}

examples

Related Question