3

My question is essentially the same as How to prevent a page break before an itemize list?. First, I don't undestand how the proposed solution (\par\nobreak\@afterheading) works. Why doesn't just \par\nobreak work? \nobreak should put there impossible penalty to pagebreak at the following glue. What does \@afterheading do?

Another thing is that it seems that the solution consumes the space between the paragraph and itemize environment. Minimal example showing the problem follows.

\documentclass[12pt, a4paper]{article}

\makeatletter
\newcommand*{\NoBreakPar}{\par\nobreak\@afterheading}
\makeatother

\begin{document}
    Let's see the following list:\NoBreakPar
    \begin{itemize}
        \item First.
        \item Second.
        \item Third.
    \end{itemize}
\end{document}
9
  • 1
    the "why" is answered by @lockstep's answer in the cited question. the \nobreak is overridden by coding defined in the beginning of (all) lists; \@afterheading counteracts this. but the removal of space before the itemize does appear to be a real problem; that should be the subject of this question, and a small example would help. (by the way, enumitem is irrelevant here, and i've removed that flag.) Jul 13, 2014 at 13:26
  • @user87690: Since you have enough reputation, you can leave a @username comment to the relevant user who posted the question and ask him/her for more explanation. I am sure, you will be answered.
    – user31729
    Jul 13, 2014 at 13:30
  • @user87690: Sorry, there was a tiny error: I meant to the user who posted the answer...
    – user31729
    Jul 13, 2014 at 13:44
  • @barbarabeeton: I've added an example. I added the enumitem tag, because both itemize and enumitem are examples of the general problem.
    – user87690
    Jul 13, 2014 at 14:01
  • @ChristianHupfer I left there the comment. I was just thinking that it increases the probability of response if I question the whole community rather than one user.
    – user87690
    Jul 13, 2014 at 14:03

4 Answers 4

3
\documentclass[12pt, a4paper]{article}
\usepackage{blindtext}

\begin{document}

\blindtext[3]

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam lobor-
tis facilisis sem. Nullam nec mi et neque pharetra sollicitudin. Praesent
imperdiet mi nec ante. Donec ullamcorper, felis non sodales commodo, lec-
tus velit ultrices augue, a dignissim nibh lectus placerat pede. Vivamus
nunc nunc, molestie ut, ultricies vel, semper in, velit. Ut porttitor.

\begin{samepage}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam lobor-
tis facilisis sem. Nullam nec mi et neque pharetra sollicitudin. Praesent
imperdiet mi nec ante.

    \begin{itemize}
        \item First.
        \item Second.
        \item Third.
    \end{itemize}

\end{samepage}

\end{document}
1
  • The problem of this solution is that you have to wrap the whole block. You cannot for example disallow pagebreak before the list but at the same time allow the break between individual items (e.g. in case when the list is too long but the paragraph before directly introduces the list and ends with colon).
    – user87690
    Jul 17, 2014 at 8:32
3

I'm starting to think that the best solution is the approach described in @lockstep's answer to the original question (How to prevent a page break before an itemize list?).

To summarize: the environments like itemize and enumerate automatically put \@beginparpenalty between the list and previous paragrapth, \@itempenalty between the items, and \@endparpenalty after the list. This is why putting \nobreak doesn't help – the penalty is overriden by automatically inserted penalty.

The default value for the penalties is -\@lowpenalty which is -51 so the break there is actually encouraged (which is a good thing if e.g. the items consist of more paragraphs. The solution of the problem is to locally change the value of either \@beginpenalty, \@itempenalty, or \@endparpenalty, depending on the desired behaviour. This change should be encapsulated in a macro, e.g. defining \NoListBreak macro setting \@beginpenalty to 10000 or \@lowpenalty, \@medpenalty, or \@highpenalty (300 if I remember), and defining similar macro \NoItemBreak setting \@itempenalty. The locality of the change is achieved by the group which enumerate or itemize environment automatically inserts.

2

Well, with the lack of judgement of a mere user:

\documentclass[12pt, a4paper]{article}

\makeatletter
\newcommand*{\NoBreakPar}{\vspace{\baselineskip}\par\nobreak\@afterheading}
\makeatother

\begin{document}
    Let's see the following list:\NoBreakPar
    \begin{itemize}
        \item First.
        \item Second.
        \item Third.
    \end{itemize}



\end{document}
3
  • How do you know that the space which should be there is \baselineskip?
    – user87690
    Jul 16, 2014 at 17:35
  • Visual diagnosis, and if you'd like more or less, just do it!
    – Keks Dose
    Jul 16, 2014 at 19:17
  • Well, visual diagnosis doesn't help with structural consistency. E.g. the space depends on some internal parameter, if the parameter is changed so is the space. And this behavior should apply also to the space introduced by \NoBreakPar. So either one has to be sure about used internal parameter or has to find another approach which preserves the original space behavior.
    – user87690
    Jul 17, 2014 at 8:36
1

I was looking for similar solutions, and what finally worked for me was to define a new environment:

\makeatletter
\newenvironment{linkpartolist}{\@beginparpenalty=10000}{}
\makeatother

and then wrap paragraph and list into it.

\begin{linkpartolist}
  Short paragraph
  \begin{itemize}
      \item First.
      \item Second.
      \item Third.
  \end{itemize}
\end{linkpartolist}

Maybe this is what @user87690 has proposed. If yes, this is the same "spelled out".

3
  • Yes, this works. Usually I prefer a syntax similar to Keks Dose's answer, so these page-breaking modifiers do not alter the structure of the source code that much.
    – user87690
    Jun 5, 2018 at 12:01
  • @user87690: Me to, but the thing is that Keks Dose's approach does not work for me. When I use \newcommand*{\linkpartolist}{\vspace{\topsep}\par\nobreak\@afterheading} it still breaks between line and list. And the penalty setting has to be limited in scope and needs { } or other group, doesn't it?
    – user52366
    Jun 5, 2018 at 15:43
  • I only meant the syntax. I used \def \NoListBreak {\@beginparpenalty=\@highpenalty} and \def \NoItemBreak {\@itempenalty=\@lowpenalty}. The locality was ensured by thy surrouning environment: e.g. \begin{proof}\hfill\NoItemBreak\begin{itemize}…\end{itemize}\end{proof}.
    – user87690
    Jun 5, 2018 at 16:30

You must log in to answer this question.

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