[Tex/LaTex] How to imitate great looking Motion Mountain ToC, including hyperlinks

counterscross-referencinghyperreftable of contentstitletoc

I wanted to customize my ToC to look more or less like the one in Motion Mountain physics textbook, including clickable page numbers. My decision was to use hyperref and titletocpackages. Now it seems like there is a problem with compatibility (I guess) of these two.

Background. Table o contents of my article-class document shows only sections and subsections. Sections (both labeled/numbered and not) are supposed to be format with basic \titlecontents, while subsections with the starred version. It looks like the latter is the cause of the bad linking.

The problem. Everytime a given section follows one with subsections, the former is improperly linked to first of these subsections. Every other section and all subsections are OK.

MWE:

\documentclass{article}

\usepackage[cp1250]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{titletoc}
    \titlecontents{section}[.5pc]%
        {\addvspace{.5pc}\normalsize\makebox[2pc][r]{\thecontentspage\hspace{1pc}}}%
        {\makebox[2.5pc][r]{\thecontentslabel\hspace{1pc}}}%
        {\makebox[2.5pc][r]{\null}}%
        {}%
% comment this starred part and it does work...
    \titlecontents*{subsection}[6.5pc]%
        {\small}{}{}%
        {\hspace{5pt}\thecontentspage}%
        [\ \textbullet\ ]

\usepackage[colorlinks,linktoc=page]{hyperref}


\begin{document}

% Frontmatter - only unnumbered/unlabeled sections
\pagenumbering{roman}
    \section*{Frontmatter Section Pre-TOC}

    % TOC ...goes to TOC.
    \clearpage
    \phantomsection
    \addcontentsline{toc}{section}{\contentsname}
    \tableofcontents

    \clearpage
    \phantomsection
    \section*{Frontmatter Section 1}
    \addcontentsline{toc}{section}{Frontmatter Section 1}

    \clearpage
    \phantomsection
    \section*{Frontmatter Section 2}
    \addcontentsline{toc}{section}{Frontmatter Section 2}

% Mainmatter - only numbered/labeled sections
\clearpage
\pagenumbering{arabic}
    \clearpage
    \section{Section 1}
        \subsection{Subsection 1.1}
        \subsection{Subsection 1.2}
        \subsection{Subsection 1.3}

    \clearpage
    \section{Section 2}

    \clearpage
    \section{Section 3}
        \subsection{Subsection 3.1}
        \subsection{Subsection 3.2}

    \clearpage
    \section{Section 4}
        \subsection{Subsection 4.1}
        \subsection{Subsection 4.2}
        \subsection{Subsection 4.3}
        \subsection{Subsection 4.4}
        \subsection{Subsection 4.5}

    \clearpage
    \section{Section 5}

    \clearpage
    \section{Section 6}
        \subsection{Subsection 6.1}
        \subsection{Subsection 6.2}
        \subsection{Subsection 6.3}

% Backmatter - all (sub)sections w/o labels
    \clearpage
    \phantomsection
    \section*{Backmatter Section 1}
    \addcontentsline{toc}{section}{Backmatter Section 1}
        \phantomsection
        \subsection*{Backmatter Subsection 1.1}
        \addcontentsline{toc}{subsection}{Backmatter Subsection 1.1}

        \phantomsection
        \subsection*{Backmatter Subsection 1.2}
        \addcontentsline{toc}{subsection}{Backmatter Subsection 1.2}

    \clearpage
    \phantomsection
    \section*{Backmatter Section 2}
    \addcontentsline{toc}{section}{Backmatter Section 2}

    \clearpage
    \phantomsection
    \section*{Backmatter Section 3}
    \addcontentsline{toc}{section}{Backmatter Section 3}

\end{document}

So it looks like it is all caused by the starred \titlecontents*

I added \clearpages just to lengthen the output file and add some pages, that does not change anything else.

Thanks in advance for helping me figure this out.

EDIT:
Maybe a possible workaround would be using etoolbox lists with custom counters, most likely with custom links, too?

EDIT 2:
Is there anybody who at least managed to reproduce the error with given MWE? 😉 I somewhat know that hyperref doesn't talk to titletoc much, but have no idea to what extent they're incompatible with each other. In other words, is my problem a common one? Or maybe the opposite: is it too localized? Answer even to that question would mean something to me 🙂

To summarize this: it seems it's all about some issues with the starred titlecontents* macro. All links are fine using the classic one — it gets messy only if you group ToC entries in one paragraph…

I did some timid attempts to work it out, found examples and made some progress… Now I see it's the hyperref thing, it's just something wrong with the link-algorithm in grouped ToC. Initially I blamed titletoc only, so tried to make my ToC look the same using other tools. That of course was a dead end, to say the least. Links were everytime wrong in the same manner. I feel helpless…

Anyway, maybe someone could give me a hand and try to work on these links only? I would appreciate the smallest feedback 🙂

Best Answer

My solution goes like this (I actually extended this to include the subsubsections too):

  1. Load hyperref w/o ToC links (option linktoc=none) to define them manually. Here I decided that sections should link to whole pages they start on, while subsections link normally.

  2. Define custom counter for numberred subsections -- for referencing, in main matter only.

  3. Customize ToC entries for sections with titletoc (it's easier).

  4. Customize Toc entries for sub- and subsubsections with redefining \l@subsection and \l@subsubsection respectively, with help of some etoolbox toggles. I could customize these entries with titletoc, but then they would not be justified and therefore look much worse.

  5. Finally, switch \hypersetup{linktoc=page} so that links on pages like List of Figures etc will work normally.


The code:

\documentclass[12pt]{article}

\usepackage[cp1250]{inputenc}
\usepackage{lmodern}        % for the looks
\usepackage{biolinum}       % for the looks
\usepackage[T1]{fontenc}

\usepackage{etoolbox}
\usepackage{titletoc}
\usepackage[colorlinks,linktoc=none]{hyperref}


\newcounter{numSubSection}
    \setcounter{numSubSection}{0}

\gpreto{\subsection}{%
    \refstepcounter{numSubSection}}%


\titlecontents{section}[0pt]%
    {\addvspace{6pt}\sffamily\bfseries\normalsize%
        \makebox[18pt][r]{%
            \hyperlink{page.\thecontentspage}{\textbf{\thecontentspage}}%
            \hspace{6pt}}}%
    {\makebox[30pt][r]{\thecontentslabel\hspace{12pt}}}%
    {\makebox[30pt][r]{\null}}%
    {}%


\makeatletter

\newlength{\TOCleftSkip}
    \setlength{\TOCleftSkip}{66pt}%
\newlength{\TOCrightSkip}
    \setlength{\TOCrightSkip}{18pt}%

\newtoggle{ifSub}
    \togglefalse{ifSub}%
\newtoggle{ifSection}
    \toggletrue{ifSection}%
\newcounter{RefSubSection}%
    \setcounter{RefSubSection}{0}%
    \renewcommand*\theRefSubSection{\@arabic\c@RefSubSection}%

\renewcommand*{\tableofcontents}{%
    \section*{\contentsname}%
    \addcontentsline{toc}{section}{\contentsname}%
    \toggletrue{ifSection}%
    \setcounter{RefSubSection}{0}%
    \@starttoc{toc}}%

\gpreto{\l@section}{%
    \nottoggle{ifSection}
        {\par%
            \addtolength{\leftskip}{-\TOCleftSkip}%
            \addtolength{\rightskip}{-\TOCrightSkip}%
            \togglefalse{ifSub}}{}%
    \toggletrue{ifSection}}%

\renewcommand*{\l@subsection}[2]{%
    \stepcounter{RefSubSection}%
    \toggletrue{ifSub}%
    \iftoggle{ifSection}
        {\togglefalse{ifSection}%
            \addtolength{\leftskip}{\TOCleftSkip}%
            \addtolength{\rightskip}{\TOCrightSkip}%
            \noindent}%
        {\unskip\begingroup\upshape\small\ \textbullet~\endgroup}%
    \begingroup%
        \upshape\small#1\ \hyperlink{numSubSection.\theRefSubSection}{\textbf{#2}}%
    \endgroup}%

\renewcommand*{\l@subsubsection}[2]{%
    \iftoggle{ifSection}
        {\togglefalse{ifSection}%
            \addtolength{\leftskip}{\TOCleftSkip}%
            \addtolength{\rightskip}{\TOCrightSkip}%
            \noindent}%
        {\iftoggle{ifSub}
            {\togglefalse{ifSub}\relax%
                \unskip\begingroup\upshape\small:\ \endgroup}%
            {\unskip\begingroup\itshape\small,\ \endgroup}}%
    \begingroup\itshape\small#1\endgroup}%

\renewcommand*{\numberline}[1]{}%

\makeatother


% solution ends here, code below is just for the example
\begin{document}

% Frontmatter - only unnumbered/unlabeled sections
\pagenumbering{roman}
    \clearpage
    \tableofcontents

    \clearpage
    \section*{Preface}
    \addcontentsline{toc}{section}{Preface}

    \clearpage
    \section*{Another Preface}
    \addcontentsline{toc}{section}{Another Preface}


% Mainmatter - only numbered/labeled sections
    \clearpage
    \addtocontents{toc}{\protect\vspace{18pt}}       % just some separation
    \pagenumbering{arabic}
    %\clearpage
    \section{First}
        \subsection{Australia}
            \subsubsection{Alpha}
            \subsubsection{Beta}
            \subsubsection{Charlie}
            \subsubsection{Delta}
            \subsubsection{Echo}
            \subsubsection{Foxtrot}
        \subsection{Brazil}
            \subsubsection{Golf}
            \subsubsection{Hotel}
            \subsubsection{India}
        \subsection{Canada}

    \clearpage
    \section{Second}

    \clearpage
    \section{Third}
        \subsection{Denmark}
            \subsubsection{Juliet}
            \subsubsection{Kilo}
            \subsubsection{Lima}
            \subsubsection{Mike}
            \subsubsection{November}
        \subsection{Egypt}
            \subsubsection{Oscar}
            \subsubsection{Papa}
            \subsubsection{Quebec}
            \subsubsection{Romeo}

    \clearpage
    \section{Fourth}
        \subsection{Georgia}
            \subsubsection{Sierra}
        \subsection{Haiti}
            \subsubsection{Tango}
            \subsubsection{Uniform}
            \subsubsection{Victor}
            \subsubsection{Whiskey}
        \subsection{Iceland}
        \subsection{Japan}
            \subsubsection{X-ray}
            \subsubsection{Yankee}
            \subsubsection{Zulu}
            \subsubsection{Alpha}
            \subsubsection{Beta}
            \subsubsection{Charlie}
            \subsubsection{Delta}
            \subsubsection{Echo}
        \subsection{Kenya}
            \subsubsection{Foxtrot}
        \subsection{Laos}
            \subsubsection{Golf}
            \subsubsection{Hotel}
            \subsubsection{India}
            \subsubsection{Juliet}
            \subsubsection{Kilo}


% Backmatter - all (sub)sections w/o labels
    \clearpage
    \addtocontents{toc}{\protect\vspace{18pt}}       % just some separation
    \hypersetup{linktoc=page}
    \section*{References}
    \addcontentsline{toc}{section}{References}

    \clearpage
    \section*{List of Figures}
    \addcontentsline{toc}{section}{List of Figures}

    \clearpage
    \section*{Index}
    \addcontentsline{toc}{section}{Index}

\end{document}

This could most likely be done much easier/prettier, but at least it does the job. Hopefully everything is quite clear ;-)


The code translates to something like this:

enter image description here

Related Question