10

I recently switched to using cleveref in my latex document. However, I have one case I still don't quite get right (or maybe it is just not covered in cleveref):

I use the subfigure-environment of the subcaptionpackage on a regular basis. In the caption of the main figure, I then use \subref{} to get only the label of the subfigure, e.g. (a) instead of 1a. The main advantage of cleveref is that I can type \cref{fig} and get the result of fig.~\ref{fig}, but this does not work for a subreference, because \cref always produces the full label (1a).

Is there a way to reproduce fig.~\subref{fig:a} using cleveref as well? I.e. can I use \cref to create a reference than only uses the subfigure label without the mainfigure label?

Edit: here is a MWE illustrating the problem:

\documentclass{article}

\usepackage{mwe}
\usepackage{subcaption}
\usepackage{cleveref}

\begin{document}

\begin{figure}
    \centering
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-a}
        \caption{Figure 1a}
        \label{fig:a}
    \end{subfigure}
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-b}
        \caption{Figure 1b}
        \label{fig:b}
    \end{subfigure}
    \caption{Main figure caption}
    \label{fig}
\end{figure}

Using subcaption, I can link to \ref{fig}, \ref{fig:a} or to \subref{fig:a} alone.
Using cleverref, I can also link to \cref{fig} and to \cref{fig:a},
However, I cannot link to \subref{fig:a} alone.

\end{document}

This produces the following result: enter image description here

Edit 2: To be extra clear: The point of using cleveref is to be able to write text references without the need to describe the nature of every label. But, if I can not create a subref version of the cref command, I am still stuck with manually typing those references, which, imho, makes not much sense. Either I use cleveref all the way, or not at all. So the question is, can I create a \cref variant of \subref?

  • Could you provide a small, complete example? – cmhughes Oct 8 '16 at 17:35
  • I was hoping the problem was clear without a MWE, but here you go... – Dux Oct 8 '16 at 17:55
  • Can you clarify you MWE, i.e., bring it in line with the question? There is no \label{fig:1a} in MWE. Anyhow, what would you like to be the result of \subref{fig:a}? Also in your MWE you are just using the same command twice, i.e. \subref{fig:a}, in what respect do you expect it to give you a different result, the second time you invoke it? Are you saying you are missing a \csubref{}command? But again what would you like to see as a result? Imho saying fig. a is pretty meaningless in a document, because it does not refer to a distinct image, unless you intend to use it in the captions. – Matthias Arras Oct 22 '16 at 16:09
  • @MatthiasArras see my edit. Sry for the typo... For what it's worth, I do not think saying "fig. a" in text is useless at all, if the figure number is clear from the context. And yes, you would definitely need such a command in a caption. – Dux Oct 22 '16 at 16:17
6

Imho changing subcaption to adapt to cleveref is the wrong strategy, it would be better if cleveref would rely in its redefinition of \refstepcounter@noarg etc on the current \@currentlabel:

\documentclass{article}

\usepackage{mwe}
\usepackage{subcaption}
\usepackage{cleveref}
\makeatletter

\def\refstepcounter@noarg#1{%
  \cref@old@refstepcounter{#1}%
  \cref@constructprefix{#1}{\cref@result}%
  \@ifundefined{cref@#1@alias}%
    {\def\@tempa{#1}}%
    {\def\@tempa{\csname cref@#1@alias\endcsname}}%
  \protected@edef\cref@currentlabel{%
    [\@tempa][\arabic{#1}][\cref@result]%
    \noexpand\@currentlabel}} %changed

\def\refstepcounter@optarg[#1]#2{%
  \cref@old@refstepcounter{#2}%
  \cref@constructprefix{#2}{\cref@result}%
  \@ifundefined{cref@#1@alias}%
    {\def\@tempa{#1}}%
    {\def\@tempa{\csname cref@#1@alias\endcsname}}%
  \protected@edef\cref@currentlabel{%
    [\@tempa][\arabic{#2}][\cref@result]%
    \noexpand\@currentlabel}}% changed   

\makeatother    
\begin{document}

\begin{figure}
    \centering
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-a}
        \caption{Figure 1a}
        \label{fig:a}
    \end{subfigure}
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-b}
        \caption{Figure 1b}
        \label{fig:b}
    \end{subfigure}
    \caption{Main figure caption}
    \label{fig}
\end{figure}

Using subcaption, I can link to \ref{fig}, \ref{fig:a} or to \subref{fig:a} alone.

Using cleverref, I can also link to \cref{fig} and to \cref{fig:a} and to \cref{sub@fig:a} alone.

\end{document}

enter image description here

4
+25

A work around is to define your own 'partially-clever' command by adding this to the preamble:

\newcommand{\csubref}[2]{\namecref{#1}~\subref{#1:#2}}

However this requires a strict labelling scheme of the type mainfigurelabel:subfigureindex so if the total float is labeled by fig as in your example subfigures must be labeled as fig:<your text here>. You then may reference the subfloat by \csubref{fig}{<your text here>}. This does not take into account other useful features of \cref like handling of multiple references. Also I would consider using the subfig package as cleverref supports it natively, it does however not solve your 'problem'. But see below for comments on that.

Your accordingly modified MWE:

\documentclass{article}

\usepackage{mwe}
\usepackage{subcaption}
\usepackage{cleveref}
\newcommand{\csubref}[2]{\namecref{#1}~\subref{#1:#2}}
\begin{document}

\begin{figure}
    \centering
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-a}
        \caption{Figure 1a}
        \label{fig:a}
    \end{subfigure}
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-b}
        \caption{Figure 1b}
        \label{fig:b}
    \end{subfigure}
    \caption{Main figure caption}
    \label{fig}
\end{figure}

Using subcaption, I can link to \ref{fig}, \ref{fig:a} or to \subref{fig:a} alone.
Using cleverref, I can also link to \cref{fig} and to \cref{fig:a},
However, I can link to \csubref{fig}{a} alone.

\end{document} 

However, in the MWE you descirbed I am still not 100% convinced of the use case, since either

  • In the captions it is redundant to refer to the figure again by using fig.
  • When the figure number is deduced from the context, so may be the talking of a figure, too, so reproducing fig. may not add substantially.

The fact that the cleverref package in combination with the subfig package do not do what you want i.e. having 'fig. a' somewhere in the text add to my notion that it is not really needed to do so.

I would consider simply styling the subref a way that makes it more naturally familiar to the reader what a or b mean by using \newcommand{\csubref}[1]{(\subref{#1})} which gives (a) or (b) and is directly associated with a subfigure caption (this is the normal behavior for the subfig package). I agree, however, that a single a appearing somewhere in the text, as is the case when you use \subref{fig:a}, is undesirable, as it is always prone to be confused with the indefinite article 'a'.

  • 1
    Thanks for the extensive answer. However, this newcommand of yours is not "smart" in the sense that I have to hardcode the fig.~ part. I would need a second one for subtables, etc... – Dux Oct 24 '16 at 7:44
  • I changed my answer to reflect at least a limited degree of cleverness of the command. You should only need one for all kind of labels now. – Matthias Arras Oct 24 '16 at 13:26
  • Thank you again, I should have thought about \namecref before. What do you mean cleveref supports subfig natively? Subgif has some serious disadvantages, first of all the limited hyperef support, and some even consider it deprecated (en.wikibooks.org/wiki/LaTeX/…) – Dux Oct 24 '16 at 14:23
  • Also, I dont believe cleveref needs the labels to be formatted in the "fig:..." style to work properly, or so I believe. I can not test it right now – Dux Oct 24 '16 at 14:24
  • I agree. cleveref does not pose restrictions on the label format. But the workaround I presented above does. With supporting natively I just mean that the cleveref manual says it it works together with the subfig package. I don't know what exactly this implies. – Matthias Arras Oct 24 '16 at 14:50
4

You can adjust the behaviour of cleveref as follows and then simply use \cref{sub@fig:a} in the text.

If you just use subcaption and look in the .aux file you will see that a \label{fig:a} in a subfigure produces to entries in the .aux file, one for fig:a, with printed value like 1a and a one for sub@fig:a with two values {a}{1}.

When you load cleveref too, then two more labels are stored fig:a@cref and sub@fig:a@cref. However by default they contain the same data and print 1a. You can modify the second one to just have the data for a by adapting the subcaption code. You can then reference it via \cref{sub@fig:a} instead of \cref{fig:a}.

Sample output

\documentclass{article}

\usepackage{mwe}
\usepackage{subcaption}
\usepackage{cleveref}

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

\crefname{subsfigure}{fig.}{figs.}

\begin{document}

\begin{figure}
    \centering
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-a}
        \caption{Figure 1a}
        \label{fig:a}
    \end{subfigure}
    \begin{subfigure}{.3\linewidth}
        \includegraphics[width=\linewidth]{image-b}
        \caption{Figure 1b}
        \label{fig:b}
    \end{subfigure}
    \caption{Main figure caption}
    \label{fig}
\end{figure}

Using subcaption, I can refer to \ref{fig}, \ref{fig:a} or to
\subref{fig:a} alone.

Using cleverref, I can also refer to \cref{fig} and to \cref{fig:a},
and similaryl \cref{fig:b}.

Now I can refer to \cref{sub@fig:a} alone, and similarly
\cref{sub@fig:b} too.

\end{document}

The appropriate macro to modify is \subcaption@@label which is responsible for generating the two entries. Just before the second entry it redefines \@currentlabel. What I have done above is also add a redefinition for \cref@currentlabel. I have done this so it associates a new type of subsfigure, and then \crefname can be used to define the associated text to put in front of the label when referenced. The code should also work subtables.

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.