[Tex/LaTex] Making mdframed paragraph behave like normal paragraphs in terms of spacing

mdframedparagraphsspacing

I'm using the mdframed package to highlight a paragraph with rules on both sides. However, the mdframed-environment creates a box for the paragraph inside of it and so the spacing around it is different form the spacing of a normal paragraph.

The following code shows the problem:

\documentclass{article}
\usepackage{mdframed}

\parindent=0pt
\newenvironment{note}{%
    \begin{mdframed}[leftmargin=\dimexpr-0.5em-3pt, innerleftmargin=0.5em,
                     rightmargin=\dimexpr-0.5em-3pt, innerrightmargin=0.5em,
                     linewidth=3pt,linecolor=red, topline=false, bottomline=false]%
}{\end{mdframed}}

\begin{document}
\Huge XYZ

XYZ

\begin{note}
XYZ
\end{note}

XYZ

xyz

\begin{note}
xyz
\end{note}

xyz
\end{document}

I guess the problem can be fixed with adjusting the inner margin/skip options for the mdframed environment, but it seems rather tricky to find the correct values to make it behave exactly like a normal paragraph. Any ideas how to get the natural paragraph spacing for that?

EDIT: To make it more clear, the prolematic part is the line-spacing before and after the framed paragraph. You can see the problem best when selecting a big font size and short paragraphs. In my example the framed block starts right at the bottom of text in the paragraph before it, but there should be some additional space/glue between both.

The opposite problem occurs at the bottom of the framed paragraph, there's too much space between it and the following paragraph.

Best Answer

Here's my version:

\documentclass{article}
\usepackage{mdframed,lipsum}

\parindent=0pt
\newmdenv[leftmargin=\dimexpr-0.5em-3pt, innerleftmargin=0.5em,
          rightmargin=\dimexpr-0.5em-3pt, innerrightmargin=0.5em,
          linewidth=3pt,linecolor=red, topline=false, bottomline=false,
          innertopmargin=0pt,innerbottommargin=0pt,skipbelow=0pt,skipabove=0pt,
         ]{notex}
\newenvironment{note}
 {\par\vskip\dimexpr\dp\strutbox-\prevdepth\relax\notex\strut\ignorespaces}
 {\par\xdef\notetpd{\the\prevdepth}\endnotex\vskip-\notetpd\relax}

\begin{document}
\leavevmode\llap{\smash{\vrule depth7\baselineskip height0pt\hskip1em}}%
\lipsum*[2]
\begin{note}
\lipsum[2]
\end{note}
\leavevmode\llap{\smash{\vrule height\baselineskip\hskip1em}}%
\lipsum[2]
\end{document}

The black rules are just to show that the alignment is correct (they can't be too near the text because mdframed applies a white background).

enter image description here

A magnified view of the top line

enter image description here

And one of the bottom line

enter image description here

At the start we ensure to skip by the glue TeX would insert and we add a strut to the first line in the note environment, so to have the correct distance between baselines. At the end we do similarly, keeping into account the depth of the last line in the note environment.

Brief explanation

mdframed sets its chunks in a \vbox which is inserted in the main vertical list; this usually upsets the interline spacing, as a \vbox has its reference point at the baseline of the last box inside it. The package tries to do clever things not to add unwanted spaces, but in this case it's not sufficient.

So we need to emulate TeX's normal behavior. The distance from one baseline and the next is the sum of \dp\strutbox and \ht\strutbox; we can insert a strut in the first line of note which makes it the correct height; but adding \dp\strutbox vertical space will usually be too much, because the last line before note may have descenders. So we end the paragraph so that \prevdepth (an internal parameter) contains the depth of the last contributed box (precisely the last line). So we can add

\vskip\dp\strutbox-\prevdepth

and all is good. Something similar we have to do at the end. We end the paragraph and define \notetpd to contain the value of \prevdepth, so we can remove a vertical space with that amount, putting everything back in synch.

Related Question