# How to make the hyperlink point to the top of linked figure and item of enumeration?

I want to create a problem booklet. Each problem numbered by enumerate has at most one figure that may either be in marginpar or float and occupy the full width.

The caption for each figure has a hyperlink to the corresponding question. From the question, we also has a link to the corresponding figure.

I use auto-generated labels

\def\qMark{Q.\arabic{chapter}.\arabic{section}.\arabic{enumi}}
\def\fMark{F.\arabic{chapter}.\arabic{section}.\arabic{enumi}}


I add \usepackage[all]{hypcap} to get a better linking behavior, i.e., clicking a hyperlink will direct us to the top of the linked object rather than to the point that requires us to adjust the view.

\documentclass[12pt]{book}
\usepackage[
a4paper,
vmargin=2cm,
outermargin=9cm,
innermargin=2cm,
marginparwidth=7cm,
marginparsep=20pt
]{geometry}

\usepackage{graphicx}
\usepackage{marginfix}
\usepackage{ifoddpage}
\usepackage{caption}

\usepackage{lipsum}

\usepackage[all]{hypcap}

\def\qMark{Q.\arabic{chapter}.\arabic{section}.\arabic{enumi}}
\def\fMark{F.\arabic{chapter}.\arabic{section}.\arabic{enumi}}

\let\tempItem=\item
\renewcommand\item{\tempItem\label{\qMark}}

\def\getQRef{Problem~\ref{\qMark}}
\def\getFRef{\figurename~\ref{\fMark}}

\newcommand\MarginFig{%
\marginpar{\includegraphics[width=\linewidth]{example-image-a}
\captionof{figure}{For \getQRef.}\label{\fMark}%
}}

\newcommand\FullFig{%
\begin{figure}[hbtp]
\checkoddpage
\edef\side{\ifoddpage l\else r\fi}%
\makebox[\textwidth][\side]{%
\parbox{\dimexpr\textwidth+\marginparwidth+\marginparsep\relax}{%
\includegraphics[width=\linewidth]{example-image-b}
\caption{For \getQRef.}
\label{\fMark}}}
\end{figure}
}

\begin{document}
\chapter{Higgs Boson}

\begin{enumerate}
\item
\MarginFig
\getFRef\
\lipsum[1]

\item
\lipsum[1]

\item
\FullFig
\lipsum[1]\getFRef.

\item
\MarginFig
\lipsum[1]\getFRef.

\item
\FullFig
\lipsum[1]\getFRef.

\item
\MarginFig
\lipsum[1]\getFRef.

\item
\lipsum[1]
\end{enumerate}

\end{document}


Unfortunately, clicking, for example, Figure 1.3 or Problem 3 does not behave as they are supposed to be. Please try them by yourself to get the idea.

How to fix this issue?

-

You can put the \label at the top of the box. (I also added some % at ends of lines)

\documentclass[12pt]{book}
\usepackage[
a4paper,
vmargin=2cm,
outermargin=9cm,
innermargin=2cm,
marginparwidth=7cm,
marginparsep=20pt
]{geometry}

\usepackage{graphicx}
\usepackage{marginfix}
\usepackage{ifoddpage}
\usepackage{caption}

\usepackage{lipsum}

\usepackage[all]{hypcap}

\def\qMark{Q.\arabic{chapter}.\arabic{section}.\arabic{enumi}}
\def\fMark{F.\arabic{chapter}.\arabic{section}.\arabic{enumi}}

\let\tempItem=\item
\renewcommand\item{\tempItem\leavevmode\label{\qMark}\ignorespaces}

\def\getQRef{Problem~\ref{\qMark}}
\def\getFRef{\figurename~\ref{\fMark}}

\makeatletter
\newcommand\MarginFig{%
\marginpar{%
\refstepcounter{figure}%
\label{\fMark}%
\let\refstepcounter\@gobble
\let\H@refstepcounter\@gobble
\let\hyper@@anchor\@gobble
\includegraphics[width=\linewidth]{example-image-a}%
\captionof{figure}{For \getQRef.}%
}}

\newcommand\FullFig{%
\begin{figure}[hbtp]%
\checkoddpage
\edef\side{\ifoddpage l\else r\fi}%
\refstepcounter{figure}%
\makebox[\textwidth][\side]{\label{\fMark}%
\parbox{\dimexpr\textwidth+\marginparwidth+\marginparsep\relax}{%
\let\refstepcounter\@gobble
\let\H@refstepcounter\@gobble
\let\hyper@@anchor\@gobble
\includegraphics[width=\linewidth]{example-image-b}%
\caption{For \getQRef.}}}%
\end{figure}%
}
\makeatother

\begin{document}
\chapter{Higgs Boson}

\begin{enumerate}
\item
\MarginFig
\getFRef\
\lipsum[1]

\item
\lipsum[1]

\item
\FullFig
\lipsum[1]\getFRef.

\item
\MarginFig
\lipsum[1]\getFRef.

\item
\FullFig
\lipsum[1]\getFRef.

\item
\MarginFig
\lipsum[1]\getFRef.

\item
\lipsum[1]
\end{enumerate}

\end{document}

-
I don't see a "Problem 3" link, just links like "Figure 1.3" in the main text which this does make link to the top Oh You mean the ones in the citation? that's your item definition. back in a bit... –  David Carlisle Jul 16 '12 at 14:47
try now, modified your \item command –  David Carlisle Jul 16 '12 at 14:50
How about a local redefinition of \caption that doesn't \refstepcounter, but just \stepcounter inside \MarginFig? That is, after issuing a manual \refstepcounter, you \def\refstepcounter{\stepcounter}. –  Werner Jul 16 '12 at 15:27
It means you have a duplicated label so one of the links won't work messing with hyperref internals... –  David Carlisle Jul 16 '12 at 15:36
@Werner or make it a no-op then I wouldn't have to add -1. testing..... –  David Carlisle Jul 16 '12 at 15:39

hypcap modifies four environments (with the option all): figure, figure*, table and table*. The following lines in hypcap.sty initiate the redefinition via \hypcapredef:

\DeclareOption{figure}{\hypcapredef{\CurrentOption}}
\DeclareOption{figure*}{\hypcapredef{\CurrentOption}}
\DeclareOption{table}{\hypcapredef{\CurrentOption}}
\DeclareOption{table*}{\hypcapredef{\CurrentOption}}
\DeclareOption{all}{%
\hypcapredef{figure}%
\hypcapredef{figure*}%
\hypcapredef{table}%
\hypcapredef{table*}%
}


The reason for this modification is because it has to place the hyper reference anchor at the start of the environment rather than at the call to \caption. So, in short, hypcap will not perform as expected if you "use it" outside of these four environments.

The way around it is to use one of those environments without making it float - that's what a \marginpar does anyway. For this, the float package comes in handy, since it provides the H float specifier. The following definition of \MarginFig therefore works as expected:

\usepackage{float}% http://ctan.org/pkg/float
\newcommand\MarginFig{%
\marginpar{%
\begin{minipage}{\marginparwidth}
\begin{figure}[H]
\includegraphics[width=\linewidth]{example-image-a}
%\captionof{figure}{For \getQRef.}\label{\fMark}%
\caption{For \getQRef.}\label{\fMark}%
\end{figure}
\end{minipage}
}}


The additional wrap inside a minipage is to ensure the proper width of the resulting figure. You may experience a difference in the vertical alignment of your \marginpar since its contents is wrapped inside a minipage. This is typical of minipage's behaviour, so some adjustments might be necessary.

-
@HiggsBoson: That could be because hyperref doesn't like it when you play around with counters when using a label. His solution could work if you modify \caption locally to not \refstepcounter, but rather just \stepcounter. –  Werner Jul 16 '12 at 15:24
probably you want to use minipage [t] positioning to avoid the vertical shift from its default centering, –  David Carlisle Jul 16 '12 at 15:38