0

I am writing a two-sided document with margins (based on the kaobook-class) and would like to add a figure to the front matter. However, when adding a captioned figure, the compiler throws an "undefined control sequence" error, claiming not to know basic commands within the figure environment.

I managed to trace the issue back to the floatrow package, which requires the facing option to be turned on, as the document is two-sided (otherwise, the captions would always be on the same side of the figures, but they need to swap depending if they are on an odd or even page). So this option has to stay on.

Curiously, I also noticed that if the pagenumbering is manually set to arabic before or within the figure environment, the issue is resolved. But unfortunately, I would like to numbering to be roman, and changing it back to roman immediately after the figure environment doesn't work. (Removing the caption works as well, but, of course that's not an option either.)

Here is an MWE:

\documentclass{scrbook}
\usepackage{graphicx}
\usepackage{floatrow}

\floatsetup[figure]{% Captions for figures
    facing=yes,%
    margins=hangright,% Put captions in the margins
    capposition=beside,%
    capbesideposition={bottom,right},%
    capbesideframe=yes,%
    capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin
    floatwidth=\textwidth,% Width of the figure equal to the width of the text
}%

\begin{document}

\frontmatter

\begin{figure}[hb]
    % \pagenumbering{arabic}
    \centering
    \includegraphics[width=\textwidth]{example-image-a}
    \caption{It's the letter A.}
    \label{fig:sample_image}
\end{figure}

\end{document}
5
  • The aux file contains \gdef\@@FBset@{\global\c@FBcnti} which is the source of the error. This was written by floatrow (using \string\c@FBcnt\thepage) but \c@FBcnti was never defined. My advice is to not use floatrow (ever). Feb 12 at 17:48
  • Floatrow creates the counter FBcnt and is tryting to set it to \thepage. However, even \setcounter{FBcnt}{\thepage} won't work when using roman numerals, and \setcounter{FBcnt}{arabic{page}} won't work unless you add \let\arabic=\relax to \protected@write, nor is \arabic{page} unique. Feb 12 at 21:11
  • Hi, thank you! I think I start to understand. Is there any way to hack this? Because unfortunately, I cannot just stop using floatrow as it's fairly well incorporated into the template that I am using. I would have to find an alternative that offers the same functionality. Is there any way to find out what FBcnt does? I could not find it in the documentation. Maybe I could set it to some arbitrary value before the figure, like -1 or 0, and then reset it afterwards?
    – mapf
    Feb 13 at 9:56
  • The problem will require a rewrite of floatrow. The way \protected@write works, \thepage is not expanded until the bottom of the page on which it is printed (about the same time as the header and footer). Feb 13 at 13:43
  • I see, thank you. In the meantime, I had another idea, but didn't manage to get it to work properly yet: I swap from roman to arabic page numbers on the relevant page, but then I use \ofoot*{\roman{page}} from the scrlayer-scrpage package to replace the default page number with a custom text, and then use the afterpage package to reset the page numbering back to roman (all while saving the page numbers in a new counter to to allow for continuous counting). Generally, this works, but I'm also using a custom pagelayout which causes the \ofoot command to be ignored.
    – mapf
    Feb 13 at 13:50

1 Answer 1

1

This creates a new counter abspage to avoid \thepage altogether. It also uses the aux file to determine which page the float wound up on.

No idea why you want [hb], but it works. Note that \clearpage will turn all floats still in the queue to [p].

The \hfill is used to place the \rlap or \llap at the right edge of the text area. It will also push images to the left edge. Instead of \centering you can use \hspace*{\fill} or \makebox[\textwidth]{...}.

\documentclass{book}
\usepackage[export]{adjustbox}% for valign
\usepackage{graphicx}

\usepackage{lipsum}% random text
\usepackage{showframe}% alignment tool

\def\bottomfraction{0.7}% default is 0.3

\newcounter{abspage}
\setcounter{abspage}{1}
\AddToHook{shipout/after}{\stepcounter{abspage}}

\newcommand{\MCright}[2][c]{% #1=t, c or b (optional), #2=\caption{...}
  \hfill\rlap{\hskip\marginparsep
    \begin{minipage}[#1]{\marginparwidth}
      \vskip-\abovecaptionskip
      #2
      \vskip-\belowcaptionskip
      \hrule height0pt
    \end{minipage}}}

\newcommand{\MCleft}[2][c]{% #1=t, c or b (optional), #2=\caption{...}
  \hfill\llap{\begin{minipage}[#1]{\marginparwidth}
    \vskip-\abovecaptionskip
    #2
    \vskip-\belowcaptionskip
    \hrule height0pt
  \end{minipage}\hskip\marginparsep\hskip\textwidth}    
    \newcounter{MCindex}
    \renewcommand{\theMCindex}{\roman{MCindex}}

\makeatletter
\newcommand{\margincaption}[2][c]{% #!=t,c or b (optional), #2=\caption{...}
  \stepcounter{MCindex}%
  \protected@write{\@auxout}{\let\theabspage\relax}%
    {\string\gdef\string\MCpage\theMCindex{\theabspage}}%
  \@ifundefined{MCpage\theMCindex}%
    {\ifodd\value{abspage} \MCright[#1]{#2}%
      \else \MCleft[#1]{#2}\fi}%
    {\ifodd\csname MCpage\theMCindex\endcsname\relax \MCright[#1]{#2}%
      \else \MCleft[#1]{#2}\fi}%
  \par}
\makeatother

\begin{document}

\frontmatter

\begin{figure}[hb]
    \includegraphics[width=\textwidth, valign=T]{example-image-a}%
    \margincaption[t]{\caption{It's the letter A.}\label{fig:sample_image}}
\end{figure}

\lipsum[1]

\begin{figure}[hb]
    \includegraphics[width=\textwidth, valign=T]{example-image-a}%
    \margincaption[t]{\caption{It's the letter A.}}
\end{figure}

\lipsum[2-3]% second float to bottom of page

\mainmatter

\end{document}
4
  • Wow, impressive. Thanks a lot! So if I understand correctly, this is basically a workaround to avoid using floatrow altogether? Is it possible to align the caption with the top of the figure? The [hb] was just an arbitrary remnant that I forgot to remove for the MWE, sorry.
    – mapf
    Feb 13 at 15:44
  • [valign=t] and [t] for \indludegraphics and minipage, respectively. Feb 13 at 15:48
  • Ah, I missed the valign=t, but for some reason, I have to set the minipage alignment to c, otherwise, the caption will start a few mm below the figure top.
    – mapf
    Feb 13 at 15:57
  • 1
    The problem with [c] is that extra lines build both up and down. I revised the solution so [valign=T] and [t] work well. \caption must put the baseline at the very top. Feb 13 at 20:43

You must log in to answer this question.

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