# Render captions above figures with \caption below \includegraphics while using endfloat

Background: My TeX file is generated from R Markdown and captions are automatically placed below included figures. Here is a minimal example of what my generated TeX file looks like:

\documentclass[man]{apa7}
\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
The figure
\caption{The caption.}
\end{figure}

\end{document}


Problem: Figure captions need to be rendered above the corresponding figure (as per APA guidelines) without moving \caption.

What I have tried: I understand that captions can be rendered above the figure without changing the code via the floatrow package and \floatsetup[figure]{style=plaintop}. However, loading floatrow interferes with endfloat, which is loaded by apa7. Specifically, figures are no longer placed at the end of the document but rendered in place:

\documentclass[man]{apa7}
\usepackage{floatrow}
\floatsetup[figure]{style=plaintop}

\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
The figure
\caption{The caption.}
\end{figure}

\end{document}


According to the documentation of endfloat, floatrow should always be loaded before endfloat (and, thus, before apa7). Hence, I try to load floatrow via \RequirePackage{} but this yields errors. I can fix some of those by undefining two lengths, but this leaves me with the following error that I can't seem to resolve:

! Missing \endcsname inserted.
\@classoptionslist
l.1453 \ProcessOptionsWithKV{floatrow}


Here's the minimal reproducible example:

\RequirePackage{floatrow}
\let\abovecaptionskip\undefined
\let\belowcaptionskip\undefined

\documentclass{apa7}

\begin{document}

Lorem ipsum

\end{document}


Note that despite the error message I get a rendered PDF file that looks as expected. Also this is not specific to apa7; I get the same error when I use the article or book document class.

• What's the reason for trying to load the package before \documentclass? Sep 17, 2020 at 20:39
• apa7 loads endfloat to place figures at the end of the document. When I load floatrow after \documentclass and, thus, after loading endfloat, figures are rendered in place rather than being delayed.
– crsh
Sep 18, 2020 at 6:19
• Note that if you use floatrow just for caption position then you can also do this by just entering the caption before the float, e.g., \begin{figure}\caption{xyz}\includegraphics{}\end{figure}, then you don't need to load floatrow at all. Sep 18, 2020 at 6:38
• Thanks for your comments. I just updated my question to provide more context and a more detailed description of the problem. As noted, my TeX is automatically generated, so I don't have control over the placement of \caption inside the figure environment.
– crsh
Sep 18, 2020 at 6:43

Interestingly, apa7 converts figure into figure*. Anyway, the basic idea is to store the caption and figure into separate saveboxes and reverse their order.

\documentclass[man]{apa7}
%\documentclass{article}
%\usepackage{endfloat}
\usepackage{lipsum}% MWE only

% udbox is a \vbox version of lrbox
\makeatletter
\def\udbox#1{%
\edef\reserved@a{%
\endgroup
\setbox#1\vbox{%
\begingroup\aftergroup}%
\def\noexpand\@currenvir{\@currenvir}%
\def\noexpand\@currenvline{\on@line}}%
\reserved@a
\@endpefalse
\color@setgroup
\ignorespaces}
\def\endudbox{\unskip\color@endgroup}
\makeatother

\newsavebox{\mycaptionbox}
\newsavebox{\myfigurebox}

\makeatletter
\let\normalmakecaption=\@makecaption
\def\@makecaption#1#2{\def\test{figure}%
\ifx\@captype\test \global\setbox\mycaptionbox=\vbox{\normalmakecaption{#1}{#2}}%
\else \normalmakecaption{#1}{#2}%
\fi}
\makeatother

\let\normalfigure=\figure
\let\endnormalfigure=\endfigure

\renewenvironment{figure}[1][tbp]{\normalfigure
\begin{udbox}{\myfigurebox}}%
{\end{udbox}\unvbox\mycaptionbox
\unvbox\myfigurebox\endnormalfigure}

\expandafter\let\expandafter\normalfigurestar\csname figure*\endcsname
\expandafter\let\expandafter\endnormalfigurestar\csname endfigure*\endcsname

\renewenvironment{figure*}[1][tbp]{\normalfigurestar
\begin{udbox}{\myfigurebox}}%
{\end{udbox}\unvbox\mycaptionbox
\unvbox\myfigurebox\endnormalfigurestar}

\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
\lipsum[1]
\caption{The caption.}
\end{figure}

\end{document}


The efloat package is doing its re-definitions of figure, figure* etc. inside \efloat@AtBeginDocument, and usually \efloat@AtBeginDocument is defined as either \@iden or \AtBeginDocument. In this case both would do the re-definitions too early since the floatrow package does its re-definitions \AtBeginDocument. So the trick to get your situation solved is to delay the re-definitions done by the endfloat package even further.

Luckily the definition of \efloat@AtBeginDocument is done with \providecommand since the author of efloat already had in mind to give the user an option to self-determine the exact moment when the re-definitions should be done: "(Note: \efloat@AtBeginDocument will be defined using \providecommand so document classes and packages can pre-define it if needed.)" (Quote taken from the efloat code documentation)

The solution below defines its own version of \efloat@AtBeginDocument, storing the content into a macro called \efloatredefinitions which could be applied later on, especially after the re-definitions of the floatrow package were already done.

% Store the code of efloat re-definitions into \efloatredefinitions
% (This code must be defined before the efloat package is loaded.)
\makeatletter
\newcommand\efloatredefinitions{}
\makeatother

\documentclass[man]{apa7}

\usepackage{floatrow}
\floatsetup[figure]{style=plaintop}

% Do the efloat re-definitions after the re-definitions of floatrow were done
%\show\efloatredefinitions
\AtBeginDocument{\efloatredefinitions} % or simply \efloatredefinitions after \begin{document}

\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
The figure
\caption{The caption.}
\end{figure}

\end{document}


P.S.: It would be nice if the endfloat package would offer an option "storeredefinitions" or similar so \PassOptionsToPackage{storeredefinitions}{endfloat} could be used instead of defining \efloat@AtBeginDocument on its own. Will write an e-mail to the author of endfloat about this...

• Beautiful, thank you!
– crsh
Sep 22, 2020 at 14:06