[Tex/LaTex] Using titletoc’s \contentspush{} to non-rigidly align titles in ToC

table of contentstitletoc

The document uses the book class. Currently I'm working on the ToC using the titletoc package.

Attached here are Screenshot-1 and Screenshot-2. The screenshots were taken at 80% zoom.

Screenshot-1:
Screenshot-1 showing Chapter 1.

Screenshot-2:
Screenshot-2 showing Chapter 100.

Here are what are marked in both screenshots:

  • Short blue line: Chapter title | Long blue line: Section number
  • Short purple line: Section title | Long purple line: Subsection number
  • Short green line: Section title | Long purple line: Subsection number
  • Short red line: Section title | Long red line: Subsection number

Overview of the problem:

Screenshot-1's misalignment is a bit subtle.
Screenshot-2's misalignment is more obvious.

Comparing both screenshots, you get the idea that the problem worsens as the chapter numbers increases from 1-digit to 2-digits to 3-digits. In the screenshots and MWE, I skipped the 2-digits chapter.

As you can see in Screenshot-2, because of misalignment there are two separate lines for each color. If the alignment was properly done, the two separate lines would line-up to make one straight line per color. The coloured lines were added using an external image editing program.

I guess the misalignment stems from the use of \contentspush{} to 'non-rigidly' align the titles (instead of using \contentslabel{} to 'rigidly' align the titles).

My questions are:

1 – [Main question] How to line-up those coloured lines while at the same time keep using \contentspush{} ?

2 – [Main question] Is there an automated way to align those coloured lines? At the moment i'm using guesswork (try-and-error) to align them.

3 – [Minor question] Some of the page numbers are not right-aligned. How to align/push the page numbers to the right margin?

4 – [Minor question] The long titles causes the Overfull \hbox warnings. How to 'silence' these warnings, at least for the ToC?

Here is the MWE:

\documentclass[a4paper,12pt,oneside]{book}

\usepackage{showframe}% to show the frames

\usepackage{titletoc}%

% chapter
\titlecontents{chapter}% <section-type>
   [5mm]% <left> % not guesswork
   {}% <above-code>
   {\bfseries\contentspush{\thecontentslabel\ \hspace{5mm}}\uppercase}% <numbered-entry-format>
   {}% <numberless-entry-format>
   {\bfseries\hfill\contentspage}% <filler-page-format>

% section (1.1)
\titlecontents{section}%
   [14mm]% guesswork
   {}%
   {\contentspush{\thecontentslabel\ \hspace{5mm}}}%
   {}%
   {\hfill\contentspage}%

% subsection (1.1.1)
\titlecontents{subsection}%
   [26mm]% guesswork
   {}%
   {\contentspush{\thecontentslabel\ \hspace{3mm}}}%
   {}%
   {\hfill\contentspage}%

% to simulate long titles
\newcommand{\lorem}{Lorem ipsum dolor sit amet, consectetuer adipiscing elit.}%

% to simulate long titles
\newcommand{\aenean}{Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
Aenean commodo ligula eget dolor.}%

\begin{document}

\tableofcontents

% chapter 1
\chapter{\lorem}

\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{9}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{99}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

% chapter 100
\setcounter{chapter}{99}
\chapter{\lorem}

\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{9}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{99}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\end{document}

Best Answer

The following modification takes care of all four questions; the idea is to use a box of fixed width (I chose 18mm to accommodate three digits) to typeset the sectional unit number inside the argument of \contenntspush; for example, for chapters:

% chapter
\titlecontents{chapter}% <section-type>
   [5mm]% <left> % not guesswork
   {}% <above-code>
   {\bfseries\contentspush{\makebox[18mm][l]{\thecontentslabel\hfill}}\uppercase}% <numbered-entry-format>
   {}% <numberless-entry-format>
   {\nolinebreak\titlerule*[1000pc]{.}\bfseries\contentspage}% <filler-page-format>

Then for sections, the first optional argument is no longer guessed but calculated as 23mm=5mm (first optional argument used for chapters) + 18mm (width of the \makebox). A similar remark applies for the other sectional units.

Instead of \hfill\contentspage I used \nolinebreak\titlerule*[1000pc]{.}\contentspage to prevent undesired line breaks between the titles and the page numbers.

The complete example code:

\documentclass[a4paper,12pt,oneside,draft]{book}
\usepackage[latin]{babel}
\usepackage{showframe}% to show the frames

\usepackage{titletoc}%

% chapter
\titlecontents{chapter}% <section-type>
   [5mm]% <left> % not guesswork
   {}% <above-code>
   {\bfseries\contentspush{\makebox[18mm][l]{\thecontentslabel\hfill}}\uppercase}% <numbered-entry-format>
   {}% <numberless-entry-format>
   {\nolinebreak\titlerule*[1000pc]{.}\bfseries\contentspage}% <filler-page-format>

% section (1.1)
\titlecontents{section}%
   [23mm]% not guesswork: 5mm+18mm from chapter settings
   {}%
   {\contentspush{\makebox[18mm][l]{\thecontentslabel\hfill}}}%
   {}%
   {\nolinebreak\titlerule*[1000pc]{.}\contentspage}%

% subsection (1.1.1)
\titlecontents{subsection}%
   [41mm]% not guesswork: 23mm+18mm from section settings
   {}%
   {\contentspush{\makebox[18mm][l]{\thecontentslabel\hfill}}}%
   {}%
   {\nolinebreak\titlerule*[1000pc]{.}\contentspage}%

% to simulate long titles
\newcommand{\lorem}{Lorem ipsum dolor sit amet, consectetuer adipiscing elit.}%

% to simulate long titles
\newcommand{\aenean}{Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
Aenean commodo ligula eget dolor.}%

\pagestyle{plain}

\begin{document}

\tableofcontents

% chapter 1
\chapter{\lorem}

\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{9}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{99}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

% chapter 100
\setcounter{chapter}{99}
\chapter{\lorem}

\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{9}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\setcounter{section}{99}
\section{\aenean}
\subsection{\aenean}
\subsection{\aenean}

\end{document}

The resulting ToC:

enter image description here

Of course, adjust the lengths according to your needs (in chapter entries, for example, the width for the \makebox could be less than 18mm).

Related Question