[Tex/LaTex] Correct hyperlink to the index

hyperrefindexing

I am writing a document using the book class, and the hyperlink to the index sends the pdf viewer a bit too far, i.e. when I click the top of the screen is at the start of the index instead of displaying the index title. Here is a MWE :

\documentclass{book}
\usepackage{hyperref}
\usepackage{makeidx}
\makeindex
\begin{document}


\cleardoublepage
\phantomsection
\addcontentsline{toc}{section}{Table of Contents}
\renewcommand{\contentsname}{Table of Contents}  % Original name = Contents
\tableofcontents
\index{foo}


\cleardoublepage
\phantomsection
\addcontentsline{toc}{chapter}{\indexname}
\printindex


\chapter{foo}
\end{document}

When I compile it and click on index, I get to that position :

How can I have the hyperlink to index send exactly to the index page, with the index title clearly visible at the top ?

Edit: Fixed the order of phantomsection and addcontentsline

Edit 2 : The log with a verbose hyperref is the following :

Package hyperref Info: Anchor `Doc-Start' on input line 18.
Package hyperref Info: Anchor `chapter*.1' on input line 20.
(D:\Travail\Bugtex\bug.toc
Package hyperref Info: bookmark on input line 1:
(hyperref)             thecounter {0}
(hyperref)             text {\contentsname }
(hyperref)             reference {chapter*.1}
(hyperref)             toclevel {0}
(hyperref)             type {toc}.
Package hyperref Info: Reference (link) `chapter*.1' on input line 2.
Package hyperref Info: Reference (link) `section*.2' on input line 3.
Package hyperref Info: Reference (link) `chapter.1' on input line 4.
)
\tf@toc=\write4
Package hyperref Info: Anchor `page.1' on input line 23.
 [1


{C:/Users/Arnaud/AppData/Local/MiKTeX/2.9/pdftex/config/pdftex.map}
Package `hyperref' Info: End of reference (link) `chapter*.1', line 2.
Package `hyperref' Info: End of reference (link) `section*.2', line 3.
Package `hyperref' Info: End of reference (link) `chapter.1', line 4.
]
 Package hyperref Info: Anchor `page.2' on input line 23.
 [2

]
Package hyperref Info: Anchor `section*.2' on input line 24.
Package hyperref Info: bookmark on input line 25:
(hyperref)             thecounter {0}
(hyperref)             text {\indexname }
(hyperref)             reference {section*.2}
(hyperref)             toclevel {0}
(hyperref)             type {toc}.
 (D:\Travail\Bugtex\bug.ind
Package hyperref Info: Reference (link) `page.1' on input line 3.
Package hyperref Info: Anchor `page.3' on input line 5.
 [3

Package `hyperref' Info: End of reference (link) `page.1', line 3.

])
Package hyperref Info: Anchor `page.4' on input line 28.
 [4


]
Package hyperref Info: Anchor `chapter.1' on input line 28.

Chapter 1.
Package hyperref Info: bookmark on input line 28:
(hyperref)             thecounter {1}
(hyperref)             text {\protect \numberline {\thechapter }foo}
(hyperref)             reference {chapter.1}
(hyperref)             toclevel {0}
(hyperref)             type {toc}.
Package atveryend Info: Empty hook `BeforeClearDocument' on input line 29.
Package hyperref Info: Anchor `page.5' on input line 29.

Best Answer

Anchor for the index title that uses \twocolumn

In the meanwhile the trouble (order of \phantomsection and \addcontentsline) with MWE is fixed and we can look at the real problem:

\cleardoublepage
\phantomsection
\addcontentsline{toc}{chapter}{\indexname}

suffers from a side effect of the optional argument of \twocolumn. The title in the optional argument is put at the top of page in one-column mode, but the current contents of the page (anchor setting) is stalled and is added after the title in two-column mode.

Therefore the internals of \begin{theindex} needs patching to get the anchor at the right place:

\listfiles
\documentclass{book}
\usepackage[verbose]{hyperref}
\usepackage{makeidx}
\makeindex

\usepackage{etoolbox}
\patchcmd{\theindex}{%
  \twocolumn[%
}{%
  \twocolumn[%
    \phantomsection
    \addcontentsline{toc}{chapter}{\indexname}%
}{}{\errmessage{Patching \string\begin{theindex} failed}}

\begin{document}

\cleardoublepage
\phantomsection
\addcontentsline{toc}{section}{Table of Contents}
\renewcommand{\contentsname}{Table of Contents}  % Original name = Contents
\tableofcontents
\index{foo}

\printindex

\chapter{foo}
\end{document}

Analysis of old MWE

Analysis part is kept, because its method remains useful for debugging similar problems.

With the old MWE of the question I get a link that is two pages early.

The following MWE just adds \listfiles and option verbose to hyperref and uses one empty line instead of two:

\listfiles
\documentclass{book}
\usepackage[verbose]{hyperref}
\usepackage{makeidx}
\makeindex
\begin{document}

\cleardoublepage
\phantomsection
\addcontentsline{toc}{section}{Table of Contents}
\renewcommand{\contentsname}{Table of Contents}  % Original name = Contents
\tableofcontents
\index{foo}

\cleardoublepage
\addcontentsline{toc}{chapter}{\indexname}
\phantomsection
\printindex

\chapter{foo} 
\end{document}

Now the .log file contains after running two times with pdflatex:

Package hyperref Info: Anchor `Doc-Start' on input line 6.
Package hyperref Info: Anchor `section*.1' on input line 9.
Package hyperref Info: bookmark on input line 10:
(hyperref)             thecounter {0.0}
(hyperref)             text {Table of Contents}
(hyperref)             reference {section*.1}
(hyperref)             toclevel {1}
(hyperref)             type {toc}.
Package hyperref Info: Anchor `chapter*.2' on input line 12.
 (./test.toc
Package hyperref Info: bookmark on input line 1:
(hyperref)             thecounter {0}
(hyperref)             text {\contentsname }
(hyperref)             reference {chapter*.2}
(hyperref)             toclevel {0}
(hyperref)             type {toc}.
Package hyperref Info: Reference (link) `chapter*.1' on input line 2.
Package hyperref Info: Reference (link) `section*.2' on input line 3.
Package hyperref Info: Reference (link) `chapter.1' on input line 4.
)
\tf@toc=\write5
\openout5 = `test.toc'.

Package hyperref Info: Anchor `page.1' on input line 15.
 [1



{/home/one/tl/tldevsrc/Master/texmf-dist/fonts/map/pdftex/updmap/pdftex.map}
Package `hyperref' Info: End of reference (link) `chapter*.1', line 2.
Package `hyperref' Info: End of reference (link) `section*.2', line 3.
Package `hyperref' Info: End of reference (link) `chapter.1', line 4.
]
Package hyperref Info: Anchor `page.2' on input line 15.
 [2

]
Package hyperref Info: bookmark on input line 16:
(hyperref)             thecounter {0}
(hyperref)             text {\indexname }
(hyperref)             reference {chapter*.2}
(hyperref)             toclevel {0}
(hyperref)             type {toc}.
Package hyperref Info: Anchor `section*.3' on input line 17.
 (./test.ind
Package hyperref Info: Reference (link) `page.1' on input line 3.
Package hyperref Info: Anchor `page.3' on input line 5.
 [3

Package `hyperref' Info: End of reference (link) `page.1', line 3.

])

Analysis:

  • Anchor Doc-Start is set automatically by hyperref at the begin of the document.
  • Anchor section*.1 is caused by the first \phantomsection before \tableofcontents
  • The bookmark for the table of contents is using the anchor before.
  • Anchor chapter*.2 is set by \chapter*{\contentsname...}. BTW, this anchor can be used instead of \phantomsection, see below.
  • Links in the table of contents:

    • section*.1: first \phantomsection before \tableofcontents
    • chapter*.2: \tableofcontents
    • chapter.1: \chapter{foo}
  • Output of page 1 with anchor page.1.

  • Output of page 2 with anchor page.2.

  • The bookmark for the index is using chapter*.2, the link generated by \thetableofcontents.

  • Anchor section*.3 is caused by \phantomsection after \addcontentsline for index.

  • Index entry links to page.1, the page location of \index{foo}.
  • Output of page 3 with anchor page.3.

Versions:

  • LaTeX: 2011/06/27
  • book: 2007/10/19 v1.4h
  • hyperref: 20112/11/06 v6.83m
  • makeidx: 2000/03/29 v1.0m

Summary:

Both the bookmark and the entry in the table of contents for the index points to the table of contents on page 1 instead to the index on page 3. This is fixed by the correct order:

\cleardoublepage
\phantomsection
\addcontentsline{toc}{...}{...}

Link for the table of contents

The previous analysis has shown, that the first \phantomsection is not needed for the table of contents:

\listfiles
\documentclass{book}
\usepackage[verbose]{hyperref}
\usepackage{bookmark}%
\usepackage{makeidx}
\makeindex

\usepackage{etoolbox}
\patchcmd{\theindex}{%
  \twocolumn[%
}{%
  \twocolumn[%
    \phantomsection
    \addcontentsline{toc}{chapter}{\indexname}%
}{}{\errmessage{Patching \string\begin{theindex} failed}}

\renewcommand*{\contentsname}{Table of Contents}

% Put `\addcontentsline` for the table of contents at the
% start of the table of contents to get on its first page
\AtBeginDocument{%
  \addtocontents{toc}{%
    \protect\addcontentsline{toc}{chapter}{\protect\contentsname}%
  }%
}

\begin{document}

\tableofcontents
\index{foo}

\printindex

\chapter{foo}
\end{document}

Because of the indirection (nested \add(to)contents(line)), an additional LaTeX run is needed. The trick is that \addcontentsline has to go between the title of the table of contents and at the end of its first page.

Related Question