0

I have a document with several lists within which I don't want a page break. In the following document:

\documentclass{article}
\usepackage[totalheight=2in]{geometry}

\begin{document}
\begin{itemize}
    \item A top level item
    \begin{itemize}
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
    \end{itemize}
    %\newpage
    \item Another top level item
    \begin{itemize}
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
    \end{itemize}
\end{itemize}
\end{document}

a break occurs in the middle of the second list. I would like to break automatically at the location of the \newpage, even if it means a less optimal break. Is there a way to prefer breaks between items instead of within an item?

I tried \usepackage{enumitem} \setlist{midpenalty=5000}, but this moves the break to just after "Another top level item". I can get what I'm looking for by enclosing Another top level item...\end{itemize} within a \parbox[t]{\textwidth}, but that seems heavy handed. Is there a better way?

It appears that https://tex.stackexchange.com/a/76495/107497 would provide a (complicated) way to automatically wrap all items within a minipage, but I was hoping for something simpler. This does appear to be the same idea as ConTeXt: Page break preference between nested itemize environments, but that is using ConTeXt.

2
  • \pagebreak[3] is the recomended solution, but it doesn.t work very often. \vfil\pagebreak[3] works, but might leave a large gap. Jan 25 at 22:31
  • Additional experiments show that you might as well use \needspace{3cm} (needspace package). The length needed is determined by trial and error. Jan 25 at 22:51

3 Answers 3

0

This shows how to calculate the space needed.

\documentclass{article}
\usepackage{needspace}
\usepackage{lipsum}

\begin{document}
\rule{1em}{30\baselineskip}

\begin{itemize}
    \item A top level item
    \begin{itemize}
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
    \end{itemize}
    \setbox0=\vbox{\leftskip\csname @totalleftmargin\endcsname
    \item Another top level item
    \begin{itemize}
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
    \end{itemize}}
    \needspace{\ht0}
    \unvbox0
\end{itemize}

\lipsum[1-4]
\end{document}
7
  • But if I'm going to box it up anyway, then I can equally put it into a parbox. This still requires that I give special treatment to such an item.
    – Teepeemm
    Jan 26 at 15:30
  • Sad but true. The question is how big does it have to be before you are willing to split it? Jan 26 at 19:45
  • The 3cm that you mentioned might turn out to be enough, so that needspace would be sufficient. The catch would be to issue \needspace{3cm} before the \item that comes before the list. I'm leaning more and more toward defining an environment {itemwithlist} as the best solution.
    – Teepeemm
    Jan 26 at 21:24
  • To answer your question, lets say that the 6 lines of text is the biggest that we have to worry about.
    – Teepeemm
    Jan 28 at 23:13
  • That would be \dimexpr 6\baselineskip+6\itemsep. Jan 28 at 23:26
0

I am pressed for time so haven't got time to test, therefore specifically not producing as MWE, -- but if you are talking about encouraging rather than preventing I think you could do something like this with penalties (adapted from one of my list formats so includes other stuff and a specific numbering format I use)

with enumitem package https://ctan.org/pkg/enumitem

\newlist{mylist}{enumerate}{6}
\setlist[mylist,1]{label=\Alph*.,ref=\Alph*,itemsep=6pt}
\setlist[mylist,2]{label=\Alph{mylisti}\arabic*.,ref=\Alph{mylisti}\arabic*,itemsep=3pt, beginpenalty=5000}
\setlist[mylist,3]{label=\alph*.,ref=\Alph{mylisti}\arabic{mylistii}.\alph*,itemsep=1pt, beginpenalty=5000}
\setlist[mylist,4]{label=(\arabic*),ref=\Alph{mylisti}\arabic{mylistii}.\alph{mylistiii}(\arabic*),itemsep=1pt, beginpenalty=5000}
\setlist[mylist,5]{label=(\alph*),ref=\Alph{mylisti}\arabic{mylistii}.\alph{mylistiii}(\arabic{mylistiv}\alph*),itemsep=1pt, beginpenalty=5000}
\setlist[mylist,6]{label=(\roman*),ref=\Alph{mylisti}\arabic{mylistii}.\alph{mylistiii}(\arabic{mylistiv}\alph{mylistv}-\roman*),itemsep=1pt, beginpenalty=5000}
\setlist[mylist]{align=left, parsep=3pt, topsep=1pt, itemindent=!, leftmargin=*}

I'll come back and revise this pending other responses

1
  • I had tried midpenalty in my original approach. beginpenalty doesn't seem to affect the page breaking of the given text.
    – Teepeemm
    Jan 26 at 22:44
0

I've gone ahead and wrapped the offending item in an environment:

\documentclass{article}
\usepackage[totalheight=2in]{geometry}
\NewDocumentEnvironment{unbreakableitem}{o}{%
 \IfValueTF{#1}{\item[#1]}{\item}%
 \begin{minipage}[t]{\linewidth}%
}{%
 \end{minipage}%
}

\begin{document}
\begin{itemize}
    \item A top level item
    \begin{itemize}
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
    \end{itemize}
    \begin{unbreakableitem}
    Another top level item
    \begin{itemize}
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
        \item A second level item
    \end{itemize}
    \end{unbreakableitem}
\end{itemize}
\end{document}

I suppose a better solution may be to automatically wrap all items in such an environment. But it seems like I would need a boolean to track if I'm already in an item (and the next \item needs to \end{minipage} first) or if it's the first such item.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .