0

Is it possible to format the \ref and \subref of a subcaption completely independently?

The manual suggests changing thesubfigure to change the the label of a subfigure and hence the output of \ref, but then this affect \subref as well.

For example, the following MWE

\documentclass{article}
\usepackage{subcaption}
\usepackage{cleveref}
\usepackage{tikz}

% and example figure
\def\exfigure#1#2{
  \begin{subfigure}[b]{0.3\linewidth}
    \centering
    \begin{tikzpicture}\path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);\end{tikzpicture}
    \renewcommand{\thesubfigure}{#1}%
    \phantomsubcaption%
    \label{#2}%
  \end{subfigure}\hfill}

\DeclareCaptionLabelFormat{subreffig}{(\emph{#2})}
\captionsetup{subrefformat=subreffig}

\begin{document}
\begin{figure}
  \exfigure{red}{subfig1}
  \exfigure{green}{subfig2}
  \exfigure{blue}{subfig3}
  \caption{Three squares. Left: \subref{subfig1}. Center: \subref{subfig2}.
    Right: \subref{subfig3}.}
  \label{fig:all}
\end{figure}

In \cref{fig:all}, we have three subfigures \cref{subfig1}
\cref{subfig2} and \cref{subfig3}.
\end{document}

The figure has the following caption

Figure 1: Three squares. Left: (red). Center: (green). Right: (blue).

This is the output I am after. However, the text afterwards has

In fig. 1, we have three subfigures fig. 1red fig. 1green and fig. 1blue.

Is it possible to change it to

In fig. 1, we have three subfigures fig. 1-[red] fig. 1-[green] and fig. 1-[blue].

Changing the definition of \thesubfigure to

\renewcommand{\thesubfigure}{-[#1]}%

gives the correct output in text, but the wrong output in the caption.

2
  • First, \subref{foo} is equivalent to \ref{sub@foo}. Rather than modify subcaption (which in turn modifies \label) it would be easier to create a new \label containing your desired format. Jul 1, 2021 at 2:31
  • If I change the definition to \renewcommand{\thesubfigure}{-[#1]}, \cref seems to work as expected (so that the reference has the correct format).
    – Tohiko
    Jul 1, 2021 at 16:09

2 Answers 2

1

I was able to get it to work without cleveref. Both subcaption and cleveref (not to mention hyperref) modify \label in many ways, producing a legion of \newlabel commands in the aux file. So I went back to basics and used \protected@write instead.

\documentclass{article}
\usepackage{subcaption}
%\usepackage{cleveref}
\usepackage{tikz}

\makeatletter
\newcommand{\sublabel}[1]{\refstepcounter{subfigure}%
  \protected@write\@auxout{}{\string\newlabel{sub@#1}{{(\string\emph{\thesubfigure})}{\thepage}}}%
  \protected@write\@auxout{}{\string\newlabel{#1}{{\thefigure-[\thesubfigure]}{\thepage}}}}
\makeatother

% and example figure
\def\exfigure#1#2{
  \begin{subfigure}[b]{0.3\linewidth}
    \centering
    \begin{tikzpicture}\path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);\end{tikzpicture}
    \renewcommand{\thesubfigure}{#1}%
    \sublabel{#2}%
  \end{subfigure}\hfill}

\begin{document}
\begin{figure}
  \exfigure{red}{subfig1}
  \exfigure{green}{subfig2}
  \exfigure{blue}{subfig3}
  \caption{Three squares. Left: \subref{subfig1}. Center: \subref{subfig2}.
    Right: \subref{subfig3}.}
  \label{fig:all}
\end{figure}

In \ref{fig:all}, we have three subfigures \ref{subfig1}
\ref{subfig2} and \ref{subfig3}.
\end{document}

This version is compatible to both cleveref and hyperref. The key is to format \thesubfigure for \cref and \@currentlabel for \ref and \subref.

\documentclass{article}
\usepackage{tikz}
\usepackage{subcaption}
\usepackage{hyperref}
\usepackage{cleveref}

\makeatletter
\newcommand{\sublabel}[2]{% #1 = color, #2 = label
  \refstepcounter{subfigure}%
  \edef\@currentlabel{(\noexpand\emph{#1})}\nosublabel{sub@#2}%
  \edef\@currentlabel{\thefigure-[#1]}\nosublabel{#2}%
  \ignorespaces}
\makeatother

% and example figure
\def\exfigure#1#2{\let\nosublabel=\label
  \begin{subfigure}[b]{0.3\linewidth}
    \centering
    \begin{tikzpicture}\path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);\end{tikzpicture}
    \renewcommand{\thesubfigure}{-[#1]}% for cref
    \sublabel{#1}{#2}
  \end{subfigure}\hfill}

\begin{document}
\begin{figure}
  \exfigure{red}{subfig1}
  \exfigure{green}{subfig2}
  \exfigure{blue}{subfig3}
  \caption{Three squares. Left: \subref{subfig1}. Center: \subref{subfig2}.
    Right: \subref{subfig3}.}
  \label{fig:all}
\end{figure}

In \cref{fig:all}, we have three subfigures \cref{subfig1}
\cref{subfig2} and \cref{subfig3}.
\end{document}

\begin{document}
\begin{figure}
  \exfigure{red}{subfig1}
  \exfigure{green}{subfig2}
  \exfigure{blue}{subfig3}
  \caption{Three squares. Left: \subref{subfig1}. Center: \subref{subfig2}.
    Right: \subref{subfig3}.}
  \label{fig:all}
\end{figure}

In \cref{fig:all}, we have three subfigures \cref{subfig1}
\cref{subfig2} and \cref{subfig3}.
\end{document}
1
  • While the solution certainly works, isn't it too low-level? even without cleverref. I was hoping to find a way to redefine some subcaption commands which set both the label and the sub@ label. In theory such a method would work for cref as well as the original ref since subcaptions works nicely with both.
    – Tohiko
    Jul 1, 2021 at 15:51
0

A possible solution based on the internals of subcaption

\documentclass{article}
\usepackage{subcaption}
\usepackage{cleveref}
\usepackage{tikz}

\newcommand{\thesubreffigure}{\thesubfigure}

\makeatletter
\renewcommand*\subcaption@@label[2]{%
  \@bsphack\begingroup
    \subcaption@ORI@label#1{#2}%
    \let\SK@\@gobbletwo
    \protected@edef\@currentlabel{\csname thesubref\@captype\endcsname}%
    \subcaption@ORI@label#1{sub@#2}%
  \endgroup\@esphack}
\makeatother

% and example figure
\def\exfigure#1#2{
  \begin{subfigure}[b]{0.3\linewidth}
    \centering
    \begin{tikzpicture}\path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);\end{tikzpicture}
    % \renewcommand{\thesubfigure}{#1}
    %
    \renewcommand{\thesubfigure}{-[#1]}%
    \renewcommand{\thesubreffigure}{#1}%
    \phantomsubcaption%
    \label{#2}%
  \end{subfigure}\hfill}

\DeclareCaptionLabelFormat{subreffig}{(\emph{#2})}
\captionsetup{subrefformat=subreffig}

\begin{document}
\begin{figure}
  \exfigure{red}{subfig1}
  \exfigure{green}{subfig2}
  \exfigure{blue}{subfig3}
  \caption{Three squares. Left: \subref{subfig1}. Center: \subref{subfig2}.
    Right: \subref{subfig3}.}
  \label{fig:all}
\end{figure}

In \cref{fig:all}, we have three subfigures \cref{subfig1}
\cref{subfig2} and \cref{subfig3}.
\end{document}

Produces the correct output for both \cref and \subref. Unfortunately does not produce the correct label when setting a caption instead of using \phantomsubcaption.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.