14

I'm creating three documents with three different headers, containing images or large banners. Is there a way to determine the head height automatically or even better a way to change the head height automatically with reference to the content?

I know LaTeX is telling me the head height is too small and I should change it to xx pt, but I would like to not have to do it manually.

A little excerpt of the beginning of one of my documents:

\documentclass[pdftex,12pt,oneside]{report}

\usepackage[pdftex]{graphicx}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{color}

\usepackage[paper = a4paper, tmargin = 2cm, bmargin = 2cm, lmargin = 2.5cm, rmargin = 2cm]{geometry}

\usepackage{fancyhdr}
\fancypagestyle{titlepage}
{
    \fancyhf{}
    \fancyhead[L]{~\\[0.5cm]\includegraphics[height=2cm]{./dhbw_logo}}
    \fancyhead[R]{~\\[0.5cm]\includegraphics[width=2cm]{./cz_logo}}
    \renewcommand{\headrulewidth}{0pt}
    \renewcommand{\footrulewidth}{0pt}
}
mforbes
  • 5,571
Chris.V
  • 721

2 Answers2

12

I do not think, it makes much sense to use an overlarge height of the titlepage's header for the whole document. Nonetheless the question is interesting in general.

Package fancyhdr already updates \headheight or \footskip, if the header or footer is too small. The following example stores the latest values of these dimension registers at the end of the document in an auxiliary file \jobname.heights. If the file exists, it is read in the preamble, before package geometry is loaded that might use the updated values for its calculations. Therefore the .aux file cannot be used for this purpose, because it is read a little too late (in \begin{document}).

\documentclass[12pt]{report}

\usepackage{atveryend}
\makeatletter
\AtVeryEndDocument{%
  \if@filesw % respect \nofiles
    \begingroup
      % same write register as environment `filecontents` uses
      \chardef\reserved@c=15 %
      \immediate\openout\reserved@c=\jobname.heights\relax
      \immediate\write\reserved@c{%
        \string\setlength{\string\headheight}{\the\headheight}%
      }%
      \immediate\write\reserved@c{%
        \string\setlength{\string\footskip}{\the\footskip}%
      }%
      \immediate\closeout\reserved@c
    \endgroup
  \fi
}
\makeatother
\InputIfFileExists{\jobname.heights}{}{}

\usepackage[
  includehead,
  includefoot,
  a6paper,
  landscape,
  showframe,
]{geometry}

\usepackage{fancyhdr}

\pagestyle{fancy}
\fancyhf{}
\chead{\Huge Header}
\cfoot{\Huge \begin{tabular}{c}Footer\\\thepage\end{tabular}}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}

\begin{document}
Hello World
\end{document}

First run

Package fancyhdr warns:

Package Fancyhdr Warning: \headheight is too small (12.0pt): 
 Make it at least 30.0pt.
 We now make it that large for the rest of the document.
 This may cause the page layout to be inconsistent, however.

Package Fancyhdr Warning: \footskip is too small (30.0pt): 
 Make it at least 50.99991pt.
 We now make it that large for the rest of the document.
 This may cause the page layout to be inconsistent, however.

And the contents of the page is displaced:

First run

Second run

The previously written \jobname.heights is used:

\setlength{\headheight}{30.0pt}
\setlength{\footskip}{50.99991pt}

There are no warnings and the page is:

Second run

Workaround for package calc

Package fancyhdr has bugs, e.g. \global\setlength that does not work, if package calc is loaded. The following code patches the macro \@fancyvbox.

\makeatletter
\def\reserved@a#1#2{\setbox0\vbox{#2}\ifdim\ht0>#1\@fancywarning
  {\string#1 is too small (\the#1): ^^J Make it at least \the\ht0.^^J
    We now make it that large for the rest of the document.^^J
    This may cause the page layout to be inconsistent, however\@gobble}%
  \dimen0=#1\global\setlength{#1}{\ht0}\ht0=\dimen0\fi
  \box0}
\ifx\reserved@a\@fancyvbox
  \typeout{Patching \noexpand\@fancyvbox from package fancyhdr.}
  \def\@fancyvbox#1#2{%
    \setbox0\vbox{#2}%
    \ifdim\ht0>#1\relax
      \@fancywarning{%
        \string#1 is too small (\the#1): ^^J%
        Make it at least \the\ht0.^^J%
        We now make it that large for the rest of the document.^^J%
        This may cause the page layout to be inconsistent, however\@gobble%
      }%
      \dimen0=#1\relax
      \global#1=\ht0\relax
      \ht0=\dimen0 %
    \fi
    \box0 %
  }
\fi
\makeatother

The code should be inserted in the preamble after package fancyhdr is loaded.

Heiko Oberdiek
  • 271,626
  • Thanks for your fast reply. Oh fancyhdr updates it already if it's too large? Nice to know. This looks really nifty and I'll try it at home right after work. The only problem left and which I probably forgot to mention is that my headers contain data in all three sections of fancyhead. Is that a problem or does your solution always choose the right \headheight? – Chris.V Jun 06 '13 at 06:02
  • @Chris.V: It does not matter, how many sections of \headheight are used. – Heiko Oberdiek Jun 06 '13 at 07:45
  • Yeah no that was my mistake. :) Hadn't thought the whole thing to the end. ^^ Thanks for your answer, it exactly does what I searched for. – Chris.V Jun 06 '13 at 18:35
  • unfortunately this does not work with the calc package, see my question http://tex.stackexchange.com/q/353243/120953. David Carlisle noted there in a comment to his answer that "it isn't really safe to use \chardef\reserved@c=15 % it could be overwritten without warning by other writing in the document. It would be better to allocate a \newwrite for this use in the preamble and use that instead of 15, or just use \@auxout and write to the aux file which would simplify things and avoid having to re-input." – jakun Feb 10 '17 at 23:07
  • @jakun The use of \reserved@c is perfect safe here: (1) The meaning of \reserved@c is locally defined in a group and the previous meaning of \reserved@c gets restored after the group. (2) Also, the code in the group does not expand macros and therefore unaffected by a previously defined \reserved@c. – Heiko Oberdiek Feb 10 '17 at 23:21
  • @jakun Write registers are a quite rare resource. Reusing an existing write register seems the better approach. In my answer, I had decided for the write register that environment filecontents uses. \@auxout is an alternative; the timing is more delicate, the .aux file must be written and the handle closed. This should be the case in the hook \AtVeryEndDocument. Or the entry is made in the .aux file in hook \AfterLastShipout. That also avoids an additional file. – Heiko Oberdiek Feb 10 '17 at 23:28
  • I have only one page with a header using \thispagestyle{fancy}. Is it possible to use the same technique constrained to just this one page? – Jan Hajer Sep 13 '18 at 09:53
  • @JanHajer Have you tried it? What is the problem? – Heiko Oberdiek Sep 13 '18 at 17:00
  • @heiko-oberdiek Indeed I did the mistake of polluting my example with a \usepackage{mathtools} which loads the calc package. As mentioned before the calc package interferes with this solution. Unfortunately the solution propsed in tex.stackexchange.com/q/353243/120953 doesn't compile for me. – Jan Hajer Sep 13 '18 at 18:51
  • @JanHajer See updated answer. It contains a patch for package calc. – Heiko Oberdiek Sep 13 '18 at 19:30
  • @heiko-oberdiek, your patch seems not to work on my machine. I have added your new code directly in front of \begin{document} of your old code. The calc package still prevents your solution from working. – Jan Hajer Oct 01 '18 at 13:08
  • @JanHajer Make a new question with a full, but minimal example, add \listfiles to get the versions of the used packages. Maybe, add a link to the new question in a comment here. – Heiko Oberdiek Oct 01 '18 at 13:19
  • @heiko-oberdiek, here is my question. Thanks for your help. – Jan Hajer Oct 01 '18 at 14:24
  • @JanHajer The internal macro prefix has changed from \@fancy to \f@nch@. Therefore, \@fancyvbox needs to be changed to \f@nch@vbox and \@fancywarning to \f@nch@warning in the patch for more recent version. – Heiko Oberdiek Oct 01 '18 at 14:56
1

Package fancyhdr already updates \headheight or \footskip

Not entirely true: for accentuated letters, fancyhdr ignore the accents and sets the heights to that of the selected fontsize.

Example:

\documentclass[a4paper, 12pt, twoside]{report}
\usepackage{fancyhdr}
  \pagestyle{fancy}
  \fancyhead[RO, LE] {}
\begin{document}
  \chapter{nothing, just setting a weird title: l\`ik\'e s\^o}
    \newpage
\end{document}

In this example, fancyhdr puts \headheight to the size of 12pt's \Large for the title of the chapter in the head. However, a title with accents is bigger than without, and LaTeX adjusts the head height at the first title with such accents, leaving the first chapters with a different head height.

This should be fancyhdr default setting, depending on language. Instead, one can correct fancyhdr's oversight, if there are chapters with accentuated letters, using calc's heightof. For french language, worst case scenario is circumflex accent, thus:

\setlength{\headheight}{\heightof{{\Large \^{E}}}}

fixes the headheight.

luneart
  • 534