5

I have an image and a table and they need to appear in the same page. The way I'm doing that right now is by wrapping them both in a figure. The problem I'm having is I'm trying to reference the table and LaTex keeps on labeling it as a figure.

\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage[colorlinks]{hyperref}
\usepackage[singlelinecheck=false]{caption}
\usepackage{booktabs}
\usepackage{threeparttable}
\usepackage{graphicx}
\graphicspath{ {./images/} }

\begin{document}

stuff stuff \autoref{table:nmr_nitro} blah blah.

\begin{figure}
\includegraphics[scale=0.4]{3-nitrobenzonitrile.png}
\captionof{figure}{3-Nitrobenzonitrile with hydrogens assignments}
\label{figure:nmr_fig_nitro}

\begin{threeparttable}
\addtocounter{footnote}{1}
\captionof{table}{NMR of 3-nitrobenzonitrile}
\label{table:nmr_nitro}

\begin{tabular}{ c c }
\toprule
\textbf{Some Data} & \textbf{Assignment} \\
\midrule
8.542; 2.0 (2H); m;        & A, B \\
7.960; 2.1 (2H); m;        & C, D \\
\bottomrule
\end{tabular}
\end{threeparttable}

\end{figure}

\end{document}

enter image description here

I found two solutions-ish to this problem. The first is to use manual instead of autoref and just manually label all my links. The other is to put \captionsetup{type=table} above my table caption but this seems like a hack. Is there any builtin, smooth way to do this?

2
  • \captionsetup{type=table} is not a hack. This is a proper solution. Using \captionof (which uses \captionsetup{type*=table} internally) is a hack which does not set a hyperref anchor etc. For this reason table:nmr_nitro points to the start of the figure when using \captionof{table}{...}, at least from hyperrefs point of view.
    – user2574
    Commented Jan 1, 2020 at 21:58
  • ...however it would be nice if using \captionof would not lead to a wrong labeled float type, so I will take a look at it. See also: gitlab.com/axelsommerfeldt/caption/issues/53
    – user2574
    Commented Jan 1, 2020 at 22:00

2 Answers 2

2

TL;DR: \captionsetup{type=table} placed before the threeparttable is the correct way to go. Don't use \captionof, use \caption instead.

Long explanation:

How does \autoref work internally? It takes the 1st part of the hyper anchor name to determine the type, afterwards it uses the type to display the name of the type plus the usual reference one would get with \ref, too.

This works perfectly when dealing with sections etc.: \section generates a hyper anchor name starting with section. and places an anchor of this name in the document, so \autoref will display something like Section 1, and when clicking on it, it will jump to the hyper anchor section.1 which was placed at the \section command.

But when dealing with floating environments like figure and table, the situation becomes bad. \caption is the command which increases the counter here, and therefore the hyper anchor will be generated here. What is bad about it? Since the hyper anchor is placed at \caption, clicking on a link will jump to the caption and not to the start of the floating environment. Especially if the caption is below the figure content this is not a satisfying user experience.

Because of this the former maintainer of hyperref (Heiko Oberdiek) invented the hypcap package. It offers a command called \capstart which will do the hyper anchor stuff and uses \@captype (= the name of the floating environment) as type. Usually this works fine. But when combining with a command like \captionof we get a problem: The hyper anchor name (including the type) was already set by \capstart:

\documentclass[12pt]{article}
\usepackage[colorlinks]{hyperref}
\usepackage{hypcap,capt-of}
\usepackage{booktabs}
\usepackage{threeparttable}

\begin{document}

stuff stuff \autoref{table:nmr_nitro} blah blah.

\begin{figure}

\capstart % Start of table
\begin{threeparttable}
\addtocounter{footnote}{1}
\captionof{table}{NMR of 3-nitrobenzonitrile}
\label{table:nmr_nitro}
\begin{tabular}{ c c }
\toprule
\textbf{Some Data} & \textbf{Assignment} \\
\midrule
8.542; 2.0 (2H); m;        & A, B \\
7.960; 2.1 (2H); m;        & C, D \\
\bottomrule
\end{tabular}
\end{threeparttable}

\end{figure}

\end{document}

This document (which does not use the caption package) leads to the same false result as your document. What to do about it? Since \capstart has no argument and uses \@captype as type, we could offer something like \capstartof which defines \@captype and does \capstart afterwards:

\documentclass[12pt]{article}
\usepackage[colorlinks]{hyperref}
\usepackage{hypcap}
\usepackage{booktabs}
\usepackage{threeparttable}

\makeatletter
\newcommand\capstartof[1]{\def\@captype{#1}\capstart}
\makeatother

\begin{document}

stuff stuff \autoref{table:nmr_nitro} blah blah.

\begin{figure}

\capstartof{table}% start of table
\begin{threeparttable}
\addtocounter{footnote}{1}
\caption{NMR of 3-nitrobenzonitrile}
\label{table:nmr_nitro}
\begin{tabular}{ c c }
\toprule
\textbf{Some Data} & \textbf{Assignment} \\
\midrule
8.542; 2.0 (2H); m;        & A, B \\
7.960; 2.1 (2H); m;        & C, D \\
\bottomrule
\end{tabular}
\end{threeparttable}

\end{figure}

\end{document}

Hurray, now everything is fine!

Note: Since \capstartof defines \@captype to table, we don't need \captionof anymore but could use the regular \caption instead.

Now back to my caption package: It has the hypcap feature implemented, and it is turned on by default. It could be turned off by using the package option hypcap=false, and in this case it would fix your problem. But because of the "wrong jump target" problem described above this is usually not what one wants. The hypcap feature is a good one since it results in good hyperlink targets.

So instead we need something like \capstartof here, a command which registers the correct type (by defining \@captype), generates a proper hyper anchor etc. Luckily, such command is already offered by the caption package and it's called \captionsetup{type=...} or \setcaptiontype{...} (which is usually the same). It's used internally every time a floating environment starts, but when dealing with use cases like yours it needs to be placed manually, just like in the \capstartof example document above:

\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage[colorlinks]{hyperref}
\usepackage[singlelinecheck=false]{caption}
\usepackage{booktabs}
\usepackage{threeparttable}
\usepackage[demo]{graphicx}
\graphicspath{ {./images/} }

\begin{document}

stuff stuff \autoref{table:nmr_nitro} blah blah.

\begin{figure}% does \captionsetup{type=figure} internally
\includegraphics[scale=0.4]{3-nitrobenzonitrile.png}
\caption{3-Nitrobenzonitrile with hydrogens assignments}
\label{figure:nmr_fig_nitro}

\captionsetup{type=table}% create new hyper anchor at start of table contents
\begin{threeparttable}
\addtocounter{footnote}{1}
\caption{NMR of 3-nitrobenzonitrile}
\label{table:nmr_nitro}
\begin{tabular}{ c c }
\toprule
\textbf{Some Data} & \textbf{Assignment} \\
\midrule
8.542; 2.0 (2H); m;        & A, B \\
7.960; 2.1 (2H); m;        & C, D \\
\bottomrule
\end{tabular}
\end{threeparttable}

\end{figure}

\end{document}

So in summary:

\captionsetup{type=table} is not a hack, it is a proper solution. This way not only the name typeset by \autoref will be fixed, but clicking on it will jump to the start of the table content, and not to the start of the figure content (or to the caption of the table).

In general \captionof should be avoided when the hyperref package is used. See also: Section "6.5 hyperref" of the caption package documentation.

P.S.: I'm sorry for the very late answer to this issue. Since I don't take a look at all new questions on SX regularly, and since there is no tag specific to my caption package, I usually miss most of the questions related to my packages, or I discover them by accident later on, like this one. So please don't hesitate to send me a link to a SX issue via e-mail, or open an issue on the Gitlab project page: https://gitlab.com/axelsommerfeldt/caption/issues Thanks!

3

This is because you put the table in a figure environment. Since you are already using the caption package, you may e.g. do

\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage[colorlinks]{hyperref}
\usepackage[singlelinecheck=false]{caption}
\usepackage{booktabs}
\usepackage{threeparttable}
\usepackage{graphicx}
\graphicspath{ {./images/} }

\begin{document}

stuff stuff \autoref{table:nmr_nitro} blah blah.

\noindent
\begin{minipage}{\textwidth}
\centering
\includegraphics[scale=0.4]{example-image-a}
\captionof{figure}{3-Nitrobenzonitrile with hydrogens assignments}
\label{figure:nmr_fig_nitro}


\addtocounter{footnote}{1}
\captionof{table}{NMR of 3-nitrobenzonitrile}
\label{table:nmr_nitro}
\begin{threeparttable}

\begin{tabular}{ c c }
\toprule
\textbf{Some Data} & \textbf{Assignment} \\
\midrule
8.542; 2.0 (2H); m;        & A, B \\
7.960; 2.1 (2H); m;        & C, D \\
\bottomrule
\end{tabular}
\end{threeparttable}
\end{minipage}


\end{document}

enter image description here

7
  • This doesnt work because I need the image and the table to be guaranteed to be on the same page.
    – FailureGod
    Commented Apr 4, 2019 at 5:11
  • @FailureGod You can certainly make them appear on one side. The question is if you want them to float or be fixed at a given page.
    – user121799
    Commented Apr 4, 2019 at 5:13
  • @FailureGod The you could for instance wrap them in a minipage or in a tabular, depending on your layout preferences.
    – user121799
    Commented Apr 4, 2019 at 5:27
  • I need them to appear at a specific place in text. Like ''' Some text <image and figure> more text ''' where the image and the figure are not broken by a pagebreak.
    – FailureGod
    Commented Apr 4, 2019 at 5:31
  • @FailureGod I added something of that sort.
    – user121799
    Commented Apr 4, 2019 at 5:32

You must log in to answer this question.

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