Footnotes in tcolorbox not in the page of the footnotemark

footnotespagetcolorbox

I have this issue with some footnotes in some tcolorboxes. I would like
to have footnotes displayed at the bottom of the page where the footnotemark
is located. Apparently it is something difficult to obtain when the tcolorbox is very long
and splitted over 2 or 3 pages (they are breakable tcolorboxes).
The problem is quite similar to

Decorate environment with vertical bars or background but keeping footnote default behavior (ie text on the correct page)

(In first place I wanted to comment on this post but I'm too "newbie" to do that (need some reputation points…)).

Apparently the core of the problem is in the LaTeX algorithm that places floats, and from the
following posts one may think that my issue has no solution.

\tcolorbox: footnote on page on which there are

However, some years later I'm wondering if someone could find a kind of TeX patch to make footnotes
placement like requested, for instance by making them have a sort of priority over other kind of float objects?

other similar question:
footnote in a tcolorbox environment

The tex patch in my preamble was found on this forum (Tcolorbox – footnotes at end of each page) to make footnotes inside the tcolorbox
appearing as regular footnotes, that is to say outside of the tcolorbox.

Any idea?

Regards,
Eric

\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[ % Define your margins here
    a4paper,
    left=2.5cm,
    right=2.5cm,
    bottom=2.5cm,
    textheight=650pt,
    footskip=50pt
    ]{geometry}

\usepackage{lipsum,changepage}
\usepackage[breakable,hooks]{tcolorbox}

\makeatletter
% restore footnote internals to those in normal page, not minipage
\def\tcb@restore@footnote{%
  \def\@mpfn{footnote}%
  \def\thempfn{\arabic{footnote}}%
  \let\@footnotetext\tcb@footnote@collect
}

% collect footnote text
\long\def\tcb@footnote@collect#1{%
  % expand \@thefnmark before appending before app to \tcb@footnote@acc
  \expandafter\gappto\expandafter\tcb@footnote@acc\expandafter{%
    \expandafter\footnotetext\expandafter[\@thefnmark]{#1}%
  }%
}

\def\tcb@footnote@use{%
  \tcb@footnote@acc
  \global\let\tcb@footnote@acc\@empty
}
\global\let\tcb@footnote@acc\@empty

\tcbset{
  % restore for every box
  every box/.style={
    before upper pre=\tcb@restore@footnote
  },
  % use for layer 1 boxes only
  every box on layer 1/.append style={
    after app=\tcb@footnote@use
  }
}
\makeatother

\begin{document}

\begin{tcolorbox}[breakable,
                  colback=blue!7!white,
                  colframe=blue!75!black,
                  title=Protocole détaillé:
                 ]

\lipsum[1-4]
Nous avons mis en suspension 
   le pellet\footnote{Egalement appelé culot en français, il correspond au fond 
  du tube dans lequel les diatomées se sont agglomérées.} 
  \lipsum[1-1]
 Nous avons ensuite introduit le contenu dans des tubes à cryogénisation pour faire 
 un shock freeze\footnote{Méthode qui consiste à plonger brusquement les tubes 
 dans de l'azote liquide afin de détériorer les membranes.}. 
Nous avons ajouté ensuite du $\beta$-mercaptoéthanol et 
du Tween qui servent à lyser\footnote{Ouvrir, voire détruire les membranes des cellules.} 
\lipsum[1-5]
\end{tcolorbox}

\end{document}

Best Answer

This writes the footnotes to the aux file, so it takes two passes. At the end of every page it checks for any footnotes on the next page and adds them to the queue. They may appear out of order wrt normal footnotes (outside tcolorbox).

Another possible problem is if a footnote is placed near the bottom of the page, in which case the footnote and its mark will cycle, never being on the same page. Use a separate \footnotemark and \footnotetext to force the placement.

\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[ % Define your margins here
    a4paper,
    left=2.5cm,
    right=2.5cm,
    bottom=2.5cm,
    textheight=650pt,
    footskip=50pt
    ]{geometry}

\usepackage{lipsum,changepage}
\usepackage[breakable,hooks]{tcolorbox}

\newif\iffootaux
\newcounter{footaux}% for \csname
\newcounter{auxpage}% to handle frontmatter etc.
\setcounter{auxpage}{1}

\makeatletter
\tcbset{every box/.style={before upper app=\tcb@footnote@setup}}

\def\tcb@footnote@setup{\let\footnotetext=\footaux
  \let\footnote=\footnoteaux}
  
\def\footnoteaux{\@ifnextchar[\@xfootnoteaux{\stepcounter{footnote}%
  \footnotemark[\thefootnote]\@footaux[\thefootnote]}}
  
\def\@xfootnoteaux[#1]{\footnotemark[#1]\@footaux[#1]}

\def\footaux{\@ifnextchar[\@footaux{\@footaux[\thefootnote]}}
\def\@footaux[#1]#2{\protected@write{\@auxout}{\let\theauxpage\relax}{\string\newfootnote{\theauxpage}{#1}{#2}}}

\newcommand{\newfootnote}[3]{% #1 = \theauxpage, #2 = \thefoontnote, #3 = text
  \ifnum#1=1\relax
    \footnotetext[#2]{#3}%
  \else
    \stepcounter{footaux}%
    \expandafter\xdef\csname footauxpage\thefootaux\endcsname{#1}%
    \expandafter\xdef\csname footauxnumber\thefootaux\endcsname{#2}%
    \expandafter\protected@xdef\csname footauxtext\thefootaux\endcsname{#3}%
  \fi}

% to run at the end of every page (debug version)
\newcommand{\addfootaux}{\loop
  \@ifundefined{footauxpage\thefootaux}{\footauxfalse}{%
    \count1=\csname footauxpage\thefootaux\endcsname\relax
    \advance\count1 by -1
    \ifnum\count1=\value{auxpage}%
      \expandafter\let\expandafter\footauxnumber\csname footauxnumber\thefootaux\endcsname
      \expandafter\let\expandafter\footauxtext\csname footauxtext\thefootaux\endcsname
      \footnotetext[\footauxnumber]{\footauxtext}%
      \footauxtrue
    \else
      \footauxfalse
    \fi}
  \iffootaux
    \global\expandafter\let\csname footauxpage\thefootaux\endcsname\relax
    \global\expandafter\let\csname footauxnumber\thefootaux\endcsname\relax
    \global\expandafter\let\csname footauxtext\thefootaux\endcsname\relax
    \stepcounter{footaux}%
  \repeat
\stepcounter{auxpage}}
\makeatother

\AtBeginDocument{\setcounter{footaux}{1}}% reset counter after \newfootnote
\AddToHook{shipout/after}{\addfootaux}

\begin{document}

\begin{tcolorbox}[breakable,
                  colback=blue!7!white,
                  colframe=blue!75!black,
                  title=Protocole détaillé:
                 ]
\let\footnotetext=\footaux
\lipsum[1-4]
Nous avons mis en suspension 
   le pellet\footnote{Egalement appelé culot en français, il correspond au fond 
  du tube dans lequel les diatomées se sont agglomérées.} 
  \lipsum[1-1]
 Nous avons ensuite introduit le contenu dans des tubes à cryogénisation pour faire 
 un shock freeze\footnote{Méthode qui consiste à plonger brusquement les tubes 
 dans de l'azote liquide afin de détériorer les membranes.}. 
Nous avons ajouté ensuite du $\beta$-mercaptoéthanol et 
du Tween qui servent à lyser\footnote{Ouvrir, voire détruire les membranes des cellules.} 
\lipsum[1-5]
\end{tcolorbox}

\end{document}
Related Question