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'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.

share|improve this question
    
I'm not sure what the problem is. Your MWE works as far as I can tell. You got the correct values by setting your leftmargin to a negative combination of the linewidth and innerleftmargin; similarly for the rightmargin. What am I missing? –  A.Ellett Dec 29 '12 at 16:55
    
Welcome to TeX.SE! It might be a little clearer (in the output) if you use the lipsum package to insert some sample text –  cmhughes Dec 29 '12 at 17:26
    
Thanks for the responses so far. Sorry that my question wasn't clear enough, I just edited the question. –  siracusa Dec 29 '12 at 17:57
add comment

2 Answers

up vote 5 down vote accepted

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.

share|improve this answer
    
Thank you very much for that answer! I understand what you do at the beginning of the framed paragraph, but could you please explain what happens at the end? Where does the space we have to remove come from? –  siracusa Dec 29 '12 at 20:53
    
@siracusa Happy to have helped. I like your nickname; or it's the real name? Siracusa is a wonderful town and I've always been a fan of Archimedes. :) –  egreg Dec 29 '12 at 21:04
    
It's not my real name, but it was chosen after that town. Incidentally, it has its origins in one of the operas from the composer you cite in your profile (which I'm a big fan of). :-) –  siracusa Dec 29 '12 at 21:53
add comment

By using the command \mdflength you can set the leftmargin and rightmargin and just focus on the other parameters or not bother to set them at all and still get the spacing correct.

\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{mdframed}
\usepackage{lipsum}
%%  This takes the approach of your MWE where you set the widths of the
%%  line and margins
\newenvironment{mynoteA}{\noindent\hspace*{\parindent}}{}
\surroundwithmdframed[linewidth=3pt,
                      linecolor=red,
                      topline=false,bottomline=false,
                       innerleftmargin=0.5em,innerrightmargin=0.5em,
                      leftmargin=\dimexpr-\mdflength{linewidth}-\mdflength{innerleftmargin},
                      rightmargin=\dimexpr-\mdflength{linewidth}-\mdflength{innerrightmargin}]{mynoteA}
%%  Here you let `mdframed` decide the values of linewidth and inner
%%  margins, but still the frame is set correctly.
\newenvironment{mynoteB}{\noindent\hspace*{\parindent}}{}
\surroundwithmdframed[linecolor=red,
                      topline=false,bottomline=false,
                      leftmargin=\dimexpr-\mdflength{linewidth}-\mdflength{innerleftmargin},
                      rightmargin=\dimexpr-\mdflength{linewidth}-\mdflength{innerrightmargin}]{mynoteB}
%%
\pagestyle{empty}
\begin{document}

\textbf{\Large{}No frame:}\par
\lipsum[1]

\textbf{\Large{}Here you preset the margins:}
\begin{mynoteA}%
\lipsum[1-2]
\end{mynoteA}

\textbf{\Large{}Here you let \texttt{mdframed} choose the lengths}
\begin{mynoteB}%
\lipsum[1-2]
\end{mynoteB}

\end{document}

There is a slight problem which becomes apparent when you don't set \parindent to 0pt. I've tried to patch it: I added the \hspace*{\parindent} to get the paragraph to indent correctly: it will work as you expect when to set \parindent to 0pt.

This is the result.

enter image description here

I chose to use \surroundwithmdframed to separate the formatting you want for the content from the formatting you want for the frame. You don't have to go this route. You can put it all in an environment like you did in your MWE.

Per your editted question, there are several more parameters you can play with to create a visual effect closer to what you want: innertopmargin and skipabove and their cousins for the bottom.

share|improve this answer
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.