[Tex/LaTex] \parskip inserts extra space after floats (and listings)

floatsparskipspacing

This question seems to be a duplicate of How to remove the skip after a listing when "\parskip" is increased with "\baselineskip"? but the answer given there doesn’t work although it’s accepted.

How can I set a \parskip which is only inserted between paragraphs. At the moment my setting leads to an extra vertical space after an [h]-float or a {lstlisting}. The latter is not used in my document but illustrates the problem, with display styled environments.* There’s no problem with equations.

problem

\documentclass[fleqn]{book}

\usepackage{parskip}

\usepackage{listings}

\begin{document}
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
\begin{equation}
xxxxx = xxxxx
\end{equation}
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX

XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
\begin{lstlisting}
LLLLLLLLLLLLLLLLLLL
\end{lstlisting}
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX

XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
\begin{figure}[h]
\rule{10cm}{2cm}
\end{figure}
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
\end{document}

I could fix this by inserting \vspace{-\parskip} but this is a bad solution—so MS Word like 😉

* I’m using an own environment created with mdframed to get framed boxes.

Best Answer

Basically I would claim what you see is a) a bug in listings and be deficiency in "here" floats in LaTex2e and probably a bug in the implementation of equation environment when it comes to the fleqn option. The parskip package is actually not doing much here and for testing I would just comment it out and use \setlength\parskip{33pt} instead.

If you do this, then you see parskip being inserted

  • around the equation environment (bug?)
  • only after the lstlisting environment (definitely bug)
  • not around the float (but the spacing there is uneven - deficiency)

If you additionally remove the fleqn option the space around equation vanishes (and indeed there shouldn't be parskip around it). Not much we can do here on this one other than to suggest using amsmath which has a proper implementation for fleqn.

Concerning listings, I would claim this is a bug of the environment as it always adds some space above and below (controllable through settings) but in addition always adds a \parskip after and does so regardless of whether this environment is surrounded by blank lines or not. A workaround would be to configure the "belowskip" to be whatever "aboveskip" is minus the parskip setting, e.g.

\setlength\parskip{33pt}  % our strange value
\lstset{aboveskip=6pt plus 2pt, belowskip=-27pt plus 2pt}

Finally the float: here the is not much you can do: if the float is in vertical mode (which it isn't in your example) then you can apply my answer in intextsep-gives-doubled-space otherwise the best I can suggest is to place a \strut in front, e.g. something like

XXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX
\strut
\begin{figure}[h]
\rule{10cm}{2cm}
\end{figure}
CCCXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXXXX

If you use \showoutput in the preamble you will see that LaTeX properly puts just \intexsep above and below the float and nothing else. However, after the float there is additionally the calculated space added to reach the next baseline. And that amount depends on whether or not the previous line as descenders (if not there there is more space added). So the strut helps to even this out.

Technically there is no way for LaTeX (well, it is a Turing machine, but with realistic effort) to place the float in the middle of the calculated space as this information is not yet known when the float is added.

Update

One way to at least automate the addition of the \strut in horizontal mode is to use the following patch:

\usepackage{etoolbox}
\makeatletter
\patchcmd{\end@float}%
    {\vadjust}{\strut\vadjust}%
    {\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\makeatother