To get a block of text to not break across pages you can put it inside a \begin{minipage}...\end{minipage}
environment. A few ways I can think to do this. All these produce the same result, the difference is in the implementation. I think I prefer option 2, which is more complicated in the preamble but seems to me simpler to use.
1. Putting each item in its own minipage.
Basically, you need to do this, and can do so manually:
\begin{questions}
\begin{minipage}{\linewidth}
\item question text
\end{minipage}
\end{questions}
This is perhaps a bit of a faff to remember, so you could define a new command to do this for you. This could be done either as an environment or as a command, though note both would change the usual practice of using \item text
because a minipage has a beginning and an end, whereas \item
just has a beginning.
1a. As an environment.
We define an environment called nobreakitem
in the premble. This environment is used instead of the \item
command. The two line breaks before \begin{minipage}
are necessary because otherwise it thinks the minipage
is part of the previous \item
and doesn't put a line break between them. It could be just used for a problematic \item
, or for all \item
s. This, to me, is a bit weird because you are doing \begin
and \end
instead of the usual \item
and it's not saving much vs. writing the above code yourself.
\documentclass{article}
\usepackage[english]{babel} % needed by blindtext
\usepackage[pangram]{blindtext} % to produce dummy text only
\usepackage{enumitem}
\newlist{questions}{enumerate}{3}
\setlist[questions,1]{label*=\textbf{\arabic*}.}
\setlist[questions,2]{label=(\alph{questionsii})}
\setlist[questions,3]{label=(\roman{questionsiii})}
\newenvironment{nobreakitem}{
\begin{minipage}{\linewidth}\item}{\end{minipage}}
\begin{document}
~\vspace{15cm} % to push the text near the page break
\begin{questions}
\begin{nobreakitem}
\Blindtext[1][4]
\end{nobreakitem}
\begin{nobreakitem}
\Blindtext[2][4]
\begin{questions}
\item \Blindtext[1][4]
\item \Blindtext[1][4]
\item \Blindtext[1][4]
\end{questions}
\end{nobreakitem}
\end{questions}
\end{document}
1b. As a command.
We define a command called \nobreakitem
in the premble. The standard \item
just applies to whatever comes after it, but here we need to tell it where to put the \end{minipage}
, so we must enclose what comes after with {}
and pass this to our command, which is an unfortunate change over \item
. Again, the line breaks in the \newcommand
definition are needed.
\documentclass{article}
\usepackage[english]{babel} % needed by blindtext
\usepackage[pangram]{blindtext} % to produce dummy text only
\usepackage{enumitem}
\newlist{questions}{enumerate}{3}
\setlist[questions,1]{label*=\textbf{\arabic*}.}
\setlist[questions,2]{label=(\alph{questionsii})}
\setlist[questions,3]{label=(\roman{questionsiii})}
\newcommand{\nobreakitem}[1]{
\begin{minipage}{\linewidth}\item #1\end{minipage}}
\begin{document}
~\vspace{15cm} % to push the text near the page break
\begin{questions}
\nobreakitem{\Blindtext[1][4]}
\nobreakitem{\Blindtext[2][4]
\begin{questions}
\item \Blindtext[1][4]
\item \Blindtext[1][4]
\item \Blindtext[1][4]
\end{questions}}
\end{questions}
\end{document}
2. An alternative that preserves the usual approach to using \item
To preserve the use of \item
in the usual way within questions, we can use a feature of enumitem
where a list can resume a previous list. Here each \begin{question}
is its own instance of \begin{questions}
wrapped inside a minipage
, but numbered as a continuation of the global set of questions. Each \begin{question}
should contain only one top-level \item
, but it can contain sub-parts (defined in the usual way via \begin{questions}
). Then each top-level question and its sub-parts won't break across pages.
The \ifthenelse
is used because the continuation counting in enumitem
requires a different command to be used for the first list than subsequent ones, and I wanted the user to avoid having to think about this.
\documentclass{article}
\usepackage[english]{babel} % needed by blindtext
\usepackage[pangram]{blindtext} % to produce dummy text only
\usepackage{enumitem}
\newlist{questions}{enumerate}{3}
\setlist[questions,1]{label*=\textbf{\arabic*}.}
\setlist[questions,2]{label=(\alph{questionsii})}
\setlist[questions,3]{label=(\roman{questionsiii})}
\usepackage{ifthen}
\gdef\questionsstarted{0}
\newenvironment{question}{\ifthenelse{\equal{\questionsstarted}{0}}{\gdef\questionsstarted{1}\begin{minipage}{\textwidth}\begin{questions}[series=questions,start=1,leftmargin=*,resume]}{\begin{minipage}{\textwidth}\begin{questions}[resume*=questions]}}{\end{questions}\end{minipage}\bigskip}
\begin{document}
~\vspace{15cm} % to push the text near the page break
\begin{question}
\item \Blindtext[1][4]
\end{question}
\begin{question}
\item \Blindtext[2][4]
\begin{questions}
\item \Blindtext[1][4]
\item \Blindtext[1][4]
\item \Blindtext[1][4]
\end{questions}
\end{question}
\end{document}
needspace
package and issue the instructionNeedspace{6\baselineskip}
right before\item \Blindtext[2][4]
. That said, I can't see what's supposed to be so objectionable about a mid-paragraph page break.needspace
though I'd need to know how many lines my question item was going to be, which feels like quite a lot of additional hassle. The context is something like an exam where there might be 4-6 questions and each question might take up a third to a half of a page and it's considered clearer for students (who might be extremely stressed by the exam) to keep all parts of a single question on the same page.