In the subcaption
package, the default way to create subfigures is when the subfigure
environment:
\documentclass{article}
\usepackage{caption}
\usepackage{subcaption}
\begin{document}
\begin{figure}
\centering
\begin{subfigure}{0.4\textwidth}
\centering
Subfigure1 is located here
\caption{Subfigure1 caption}
\label{subfig:1}
\end{subfigure}
\begin{subfigure}{0.4\textwidth}
\centering
Subfigure2 is located here
\caption{Subfigure2 caption}
\label{subfig:2}
\end{subfigure}
\caption{Figure caption}
\label{fig}
\end{figure}
\end{document}
I like this syntax, especially in that the figure comes first, then the caption, then the label for the caption. However, I don't like having to specify the \textwidth
within the environment. I would prefer that this parameter be optional with the default value being the width of the figure.
One solution to fix this problem is to use a savebox, but then source for the figure is (slightly) divorced from its primary location of use.
The subcaption
package provides a solution for this problem via the \subcaptionbox
command:
\documentclass{article}
\usepackage{caption}
\usepackage{subcaption}
\begin{document}
\begin{figure}
\centering
\subcaptionbox{Subfigure1 caption\label{subfig:1}}{
\centering
Subfigure1 is located here}
\subcaptionbox{Subfigure2 caption\label{subfig:2}}{
\centering
Subfigure2 is located here}
\caption{Figure caption}
\label{fig}
\end{figure}
\end{document}
Now specifying \textwidth
is optional and defaults to the width of the figure, but the source is much less readable. I dislike this solution for several reasons:
- It is easier to write, read, and understand large amounts of code placed within
\begin{}...\end{}
then within\someCommand{...}
. (It is so easy to use the wrong number of curly braces.) - The figure, caption, and label out written out of order from the way they are typeset (by default), which is the order in which I think about them.
- The location to place the caption is not explicit. (It is just a required value to the
\subcaptionbox
placed between some{}
's, so a fellow coauthor that doesn't know this syntax won't know how to add a caption if it is currently blank.)
Question:
Is there a way to get the best of both worlds? How can I get behavior equivalent to using the subfigure
environment but with the specification of \textwidth
being optional (and defaulting to the width of the figure)?
(This question is about the subcaption
package because it seems that this is the best package for subfigures. I am open to suggestions that another package is better and fulfills my requirements.)
Best Answer
This doesn't support all the features of
\subcaptionbox
: the optional argument<inner-pos>
can't be expressed.The optional argument to the
xsubcaption
environment is the explicit width of the subfigure.I use the
environ
package to collect the environment's body in the macro\BODY
. Then I check whether\caption
appears in the body; if so I check whether it has an optional argument. In caption (and the "list caption", if present) is stored in a macro and then the whole\subcaptionbox
instruction is built from the various parts (when the body is typeset,\caption
is redefined to do nothing).(Added) The same checks are performed to catch a
\label
command outside the argument of\caption
(both ways are supported, of course).Finally the
\subcaptionbox
macro with all arguments determined with the code above is executed. It appears to be complicated, but it's not really difficult: it's a standard way to catch the presence of some token (\caption
and\label
) in a list of tokens, in this case the contents of the environment, which is available as the expansion of\BODY
.