The following patch can be used for tcolorbox
version 3.32
and prior. It is incorporated in tcolorbox
version 3.33 (2014/12/11)
and higher. To revert to the old behavior before 3.33
, the option ignore nobreak
can be applied.
As I wrote in my comments, I fear that there is no global solution for the problem. But I experimented with a patch which might be helpful for many use cases. The patch code tries to estimate the space needed after a heading. If it is very probable that the box or the first part of the box does not fit on the current page, the \vspace{...}\null\vspace{-...}
trick of yours is applied to move everything to the next page including the heading.
The space estimation can fail especially, if the box contains a large unbreakable content as in your example. In this case, a warning is given to detect such problems in long documents. One manual solution is to enlarge the lines before break
value to match the unbreakable content. Currently, I do not see an automatic way.
The following code is an experimental patch. If it prooves to be stable, I want to put it into an official version, but there have to be many tests before that. If you see (new) problems with it or if you can improve it, feel free to comment. The main part is \tcb@handle@nobreak
, the rest is some slightly changed current code.
\documentclass[]{article}
\usepackage[many]{tcolorbox}
\usepackage{lipsum}
\tracingpages=1
\makeatletter
\def\tcb@do@nobreak@warning{%
\tcb@warning{Using nobreak failed. Try to enlarge `lines before break' or set page breaks manually}%
}
\def\tcb@handle@nobreak{%
\tcb@enlbreak@init%
\tcb@breakat@init%
\tcb@comp@h@page%
\tcbdimto\tcb@h@page{\tcb@h@page-\baselineskip}% security surcharge
\tcb@comp@h@total@standalone%
\tcb@check@for@final@box%
\iftcb@final@box%
\else%
\ifdim\dimexpr\tcb@h@page-\tcb@h@padding-\tcb@h@padtitle<\kvtcb@breakminlines\baselineskip\relax%
\tcbdimto\tcb@h@page{\tcb@h@page+3\baselineskip}%
\vspace{\tcb@h@page}%
{\parskip\z@\nointerlineskip\noindent}%
\vspace{-\tcb@h@page}%
\fi%
\fi%
}
\def\tcb@prepare@break@operation{%
\let\tcb@nobreak@warning\@empty%
\@ifundefined{columnbreak}{\tcb@multicolfalse}{%
\ifnum\doublecol@number>\z@ %
\tcb@multicoltrue%
\else%
\tcb@multicolfalse%
\fi}%
\ifx\kvtcb@float\@empty%
\if@nobreak%
\tcb@handle@nobreak%
\let\tcb@nobreak@warning\tcb@do@nobreak@warning%
\else%
\kvtcb@beforebox%
\fi%
\def\kvtcb@beforebox{\parskip\z@\nointerlineskip\noindent}%
\noindent% applies parskip
\vskip\lineskip{\parskip\z@\par\vskip\z@}\bgroup\@nobreakfalse\addpenalty\z@\egroup% force update vertical list
\tcb@break@allowedtrue%
\tcb@enlbreak@init%
\else%
\tcb@break@allowedfalse%
\fi%
}
\def\tcb@split@start{%
\tcb@breakat@init%
\tcb@comp@h@page%
% height calculation
\tcb@comp@h@total@standalone%
%
\let\tcb@split@next=\relax%
\tcb@check@for@final@box%
\iftcb@final@box%
\tcb@drawcolorbox@standalone%
\else
\iftcb@break@allowed%
\ifdim\dimexpr\tcb@h@page-\tcb@h@padding-\tcb@h@padtitle<\kvtcb@breakminlines\baselineskip\relax%
\iftcb@multicol\columnbreak\else\pagebreak\fi%
\tcb@nobreak@warning%
\tcb@enlbreak@init\tcb@break@allowedfalse%
\tcb@comp@h@page%
\tcb@check@for@final@box%
\iftcb@final@box%
\tcb@drawcolorbox@standalone%
\else
\let\tcb@split@next=\tcb@split@first%
\fi
\else%
\let\tcb@split@next=\tcb@split@first%
\fi
\else%
\let\tcb@split@next=\tcb@split@first%
\fi%
\fi%
\tcb@split@next%
}
\def\tcb@split@first{%
\setcounter{tcbbreakpart}{1}%
\ifx\kvtcb@float\@empty%
\iftcb@vfillbeforefirst%
\let\tcb@before@first=\vfill%
\else%
\let\tcb@before@first=\@empty%
\fi%
\let\tcb@before@middle=\@empty%
\let\tcb@before@last=\@empty%
\iftcb@multicol%
\long\def\tcb@after@first{\par}% using \columnbreak here kills multicols' algortihm sometimes
\long\def\tcb@after@middle{\par\vfill}%
\else%
\long\def\tcb@after@first{\par\pagebreak\tcb@enlbreak@next}%
\long\def\tcb@after@middle{\par\vfill\eject\tcb@enlbreak@next}%
\fi%
\let\tcb@after@last=\par%
\else%
\edef\tcb@before@first{\noexpand\tcb@float@env@begin{tcbfloat}[\kvtcb@float]\noexpand\kvtcb@everyfloat}%
\let\tcb@before@middle=\tcb@before@first%
\let\tcb@before@last=\tcb@before@first%
\let\tcb@after@first=\tcb@float@env@end%
\let\tcb@after@middle=\tcb@float@env@end%
\let\tcb@after@last=\tcb@float@env@end%
\fi%
%
\edef\kvtcb@skin@@first{\kvtcb@skin@first}%
\edef\kvtcb@skin@@middle{\kvtcb@skin@middle}%
\edef\kvtcb@skin@@last{\kvtcb@skin@last}%
%
\let\tcb@h@breaksep@first=\kvtcb@bottomsep%
\tcbdimto\tcb@h@breaksep@middle{\kvtcb@bottomsep+\kvtcb@topsep}%
\let\tcb@h@breaksep@last=\kvtcb@topsep%
\tcbdimto\tcb@h@padding@first{\kvtcb@bbtop@stand+\kvtcb@bbbottom@break+\kvtcb@top@rule@stand+\kvtcb@bottom@rule@break+\tcb@h@breaksep@first+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
\tcbdimto\tcb@h@padding@middle{\kvtcb@bbtop@break+\kvtcb@bbbottom@break+\kvtcb@top@rule@break+\kvtcb@bottom@rule@break+\tcb@h@breaksep@middle+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
\tcbdimto\tcb@h@padding@last{\kvtcb@bbtop@break+\kvtcb@bbbottom@stand+\kvtcb@top@rule@break+\kvtcb@bottom@rule@stand+\tcb@h@breaksep@last+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
%
\tcb@split@setstate@first%
%
\splittopskip=0pt%
\splitmaxdepth=0pt%
\edef\tcb@thevfuzz{\the\vfuzz}%
\edef\tcb@thevbadness{\the\vbadness}%
%
\tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
\tcb@swap{\tcb@totallowerbox}{\tcb@lowerbox}%
%
\let\tcb@split@next=\relax%
\tcbdimto\tcb@split@dim{\tcb@h@page-\tcb@h@padding@first-\tcb@h@padtitle}%
\ifdim\tcb@split@dim<\tcb@h@upper\relax%
\tcb@split@upper@box%
\ifdim\wd\tcb@totalupperbox=0pt\relax%
\iftcb@lowerspace%
\tcb@sdraw@U%
\let\tcb@split@next=\tcb@split@SL%
\else%
\tcb@split@force@standalone%
\tcb@drawcolorbox@standalone%
\fi%
\else%
\ifdim\dimexpr\tcb@h@upper=0pt\relax%
\iftcb@break@allowed
\tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
\tcb@swap{\tcb@totallowerbox}{\tcb@lowerbox}%
\tcbdimto\tcb@h@upper{\ht\tcb@upperbox+\dp\tcb@upperbox}%
\tcbdimto\tcb@h@lower{\ht\tcb@lowerbox+\dp\tcb@lowerbox}%
\iftcb@multicol\columnbreak\else\pagebreak\fi%
\tcb@nobreak@warning%
\tcb@enlbreak@init\tcb@break@allowedfalse%
\let\tcb@split@next=\tcb@split@start%
\else%
\tcb@sdraw@U%
\let\tcb@split@next=\tcb@split@USL%
\fi%
\else%
\tcb@sdraw@U%
\let\tcb@split@next=\tcb@split@USL%
\fi%
\fi%
\else%
\tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
\tcbdimto\tcb@split@dim{\tcb@split@dim-\tcb@h@upper-\tcb@h@segment}
\ifdim\tcb@split@dim<\kvtcb@breakminlines\baselineskip\relax%
\tcb@sdraw@U%
\iftcb@lowerspace%
\let\tcb@split@next=\tcb@split@SL%
\else%
\let\tcb@split@next=\tcb@split@USL%
\fi%
\else
\tcb@split@lower@box%
\ifdim\wd\tcb@totallowerbox=0pt\relax%
\tcb@split@force@standalone%
\tcb@drawcolorbox@standalone%
\else%
\tcb@sdraw@USL%
\let\tcb@split@next=\tcb@split@L%
\fi%
\fi%
\fi%
\tcb@split@next%
}
\makeatother
\begin{document}
\lipsum[1-4]
\section{title}
\begin{tcolorbox}[enhanced,breakable,%
lines before break=10,% commenting this issues a warning
]
\rule{1cm}{10\baselineskip}
\lipsum[1]
\end{tcolorbox}
\clearpage
\lipsum[1-4]
\rule{1cm}{6mm}
\section{Normal case}%
\begin{tcolorbox}[enhanced,breakable]
\lipsum[1]
\end{tcolorbox}
\end{document}
I had the same issue with a document of mine and what fixed the problem for me was this answer from egreg, so I included the code here too.
\RenewDocumentEnvironment{multicols}{mO{}}
{%
\ifnum#1=1
#2%
\else % More than 1 column
\multicolmulticols{#1}[#2]
\fi
}
{%
\ifnum#1=1
\else % More than 1 column
\endmulticolmulticols
\fi
}
I hope this is what you were looking for (full MWE below).
\documentclass[a4paper,]{article}
\usepackage{lipsum} %to use lipsum
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{multicol}
\usepackage[svgnames]{xcolor}
\usepackage{graphicx}
\usepackage[colorinlistoftodos]{todonotes}
\usepackage[sfdefault,thin]{roboto}
\usepackage{fullpage}
\usepackage{longtable}
\usepackage[many]{tcolorbox}
\usepackage{xparse}
\tcbuselibrary{skins,breakable}
\newenvironment{tada}
{\begin{tcolorbox}[enhanced jigsaw, colback=Green!14!white,
colframe=Green!10!blue!29!white,
sharp corners, breakable]}{\end{tcolorbox}}
%
\let\multicolmulticols\multicols
\let\endmulticolmulticols\endmulticols
\RenewDocumentEnvironment{multicols}{mO{}}
{%
\ifnum#1=1
#2%
\else % More than 1 column
\multicolmulticols{#1}[#2]
\fi
}
{%
\ifnum#1=1
\else % More than 1 column
\endmulticolmulticols
\fi
}
%
\begin{document}
\begin{multicols}{1}
\begin{tada}
\lipsum[1]
\end{tada}
\lipsum[1]
\end{multicols}
\begin{multicols}{2}
\lipsum[1]
\begin{tada}
\lipsum[2-4]
\end{tada}
\lipsum[5]
\end{multicols}
\end{document}
Best Answer
I would do such stuff by using a
tcbraster
ortcbitemize
inside an outertcolorbox
. The following code example creates colored stripes in blue and red, but every stripe could be given an individual color: