Using mdframed
or tcolorbox
(my existing code base uses mdframed
, I'm interested in moving to tcolorbox
), I want to have three things:
- vertical space between the pretty box and the next paragraph, but
- no page break or column break in that vertical space, at least one line of text must be present (two would be better, but I'll settle for one for now), and
- I don't want to break the pretty box.
Starting with this MWE:
\documentclass[letterpaper,10pt,twocolumn,twoside,extrafontsizes]{article}
\usepackage{lipsum}
\usepackage{fp}
\usepackage{mdframed}
\usepackage{printlen}
\newlength{\testskip}
\setlength{\testskip}{1\baselineskip plus 0.5\baselineskip minus 0.5\baselineskip}
\newenvironment{test}{
\begin{mdframed}
}{
\end{mdframed}
}
\title{Suppressing Page Breaks MWE}
\begin{document}
\maketitle
\lipsum[1]
\lipsum[2]
\lipsum[3]
\lipsum[4]
\lipsum[5]
\begin{test}
Testing 1 mdframed
\end{test}
\lipsum[6]
\lipsum[7]
\end{document}
Adding \nopagebreak
gets me part way.
\newenvironment{test}{
\begin{mdframed}
}{
\end{mdframed}\nopagebreak
}
This pulls the paragraphs a bit closer together to make room for one line of text and copies the line of text from the next page. If I add \vskip0.5\baselineskip
above \lipsum[5]
there isn't enough space to reduce, and the mdframed
gets pushed to the next page.
So far, so good… but I cannot find a way to add vertical space between the mdframed
and the next paragraph. Inserting \vskip0.5\baselineskip
or vspace{0.5\baselineskip}
apparently not only inserts space but says it's a wonderful place for a page break.
It appears the skipbelow
parameter of mdframed
does a \vskip
, so that leaves me in the same situation.
I know of the needspace
package, but I can't predict how big the mdframed
is going to be. If I need to I think I can store the mdframed
height in the aux
file and use that when laying out, but I'd rather not.
(When I try using tcolorbox
in a similar manner it looks like \nopagebreak
doesn't do anything at all — either there is enough room for a line of text, or there is not, and that's all there is to it.)
It appears also that while this did work at the page break, it didn't seem to make a difference at the column break (preamble unchanged)
\title{Suppressing Page Breaks MWE}
\begin{document}
\maketitle
\lipsum[1]
\vskip4\testskip
\lipsum[2]
\begin{test}
Testing 1 mdframed
\end{test}
\lipsum[3]
\lipsum[4]
\lipsum[5]
\lipsum[6]
\lipsum[7]
\end{document}
(For context, this is for a game reference book with many statblocks — name and a set of statistics about the thing — that I don't want to break up because reading stats across page boundaries is hard. Right now I'm adjusting them by hand, inserting or removing vertical space and breaks before or after the game entities as needed. I'd like to automate this more, and if I can get mdframed
to allow space after it that doesn't cause a page break or column break that would do what I'm aiming for. Yes, it's a bit ugly, but it's eminently usable for my purpose.)
Late-Night Ah-Ha!… that didn't work
Obviously, wrapping the mdframed
with a minipage
should let me put some vertical space after the mdframed
and then a \nopagebreak
after!
\newenvironment{test}{
\noindent\begin{minipage}{\linewidth}
\begin{mdframed}
}{
\end{mdframed}\bigskip\end{minipage}\nopagebreak
}
did not do as I had hoped. I think either the skip or the minipage
still causes the nopagebreak
to be ignored.
2017-01-15 Update — \needspace
acting oddly
The needspace
solution suggested by @Schweinebacke almost worked, but I find cases where it doesn't. I cannot yet replicate them, but I can describe the symptoms.
- I have in front of me a page with a displayed
\pagetotal
of 461.9377pt and a\pagegoal
of 682pt. - The dimension passed to
\needspace
is 138.37pt. As far as I can tell, this should fit (461pt+138pt = about 600pt; about 80pt, over an inch, left over). - Block got moved to the next page, and after the block is output I have a
\pagetotal
of 601.18pt (which is what it should have been on the previous page, had the block appeared there).
This does not happen consistently. Most often, \needspace
works as expected: the block gets moved and the \pagetotal
is reset to 0 before the block is output (i.e. I have in front of me one where the space needed was 136.55pt, \pagetotal
after the block is 124.55pt (I wanted "height of block plus one line of text, \bigskip
is about 12pt, so this all adds up more or less).
It looks as though \needspace
determines the requested space is available, then the entire thing gets moved despite there evidently being enough space.
Am I doing something wrong with \needspace
in my answer below?
2017-01-18 Update: Why use \needspace
at all?
Browsing other questions, I stumbled on something I perhaps should have considered earlier… these blocks are being used much as fancy — and big — headings. This includes possibly being included in the Table of Contents.
Is there any reason I couldn't use \@startsection
? Treat it like a section (positive space above and below) with a potentially big section heading, then call it done.
Simple answer… it doesn't work the way I need. I could use it to, say, draw a pretty frame around the section heading (useful to know), but the other elements that I need (title and body content in the frame) really aren't suited for section-style semantics. Which I would have realized had I thought about it for a moment.
Best Answer
mdframed
(andtcolorbox
) have their own page break algorithms to allow breaks in the boxes. So it is a little bit complicated to put them into another box. But you can put the contents of amdframed
into a box and output this box inside themdframed
. You can measure the height and depth of this box and use the result (and some extra space) forneedspace
:Nevertheless, if you do not want a page break inside
mdframed
, there is no need to even usemdframed
. You can simply put the text in a box and frame it yourself using whatever kind of frame you want: