Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

This is a question triggered by Automatically remove page number in one-page documents.

When activating the fancyhdr package, it is necessary to clear the headers, which I do below with \fancyhf{}, because it will otherwise print MY FIRST SECTION as the header for the document below. It will still, however, print the ruler below the empty header, so I remove this with \renewcommand{\headrulewidth}{0pt}.

The problem is this: I put these lines in my custom .sty file. When I do want a header in my document, I clearly don't want to hard-wire that header into my .sty file. It should rather go in the preamble of the document I am writing, as done below. But since I put \renewcommand{\headrulewidth}{0pt} in my .sty file, it will now not print any ruler, even though I've added a header.

What I am looking for is a way for LaTeX to automatically activate \renewcommand{\headrulewidth}{0pt} only when the header is actually empty.

\documentclass{article}
\usepackage{filecontents}

\begin{filecontents}{mystyle.sty}
%% My package starts here
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mystyle}
\usepackage{fancyhdr}
    \pagestyle{fancy}
    \fancyhf{}
    \renewcommand{\headrulewidth}{0pt}
\endinput
%% And ends here
\end{filecontents}

\usepackage{mystyle}
\fancyhead[C]{Woah! There's no ruler here!}

\begin{document}
\section{My first section}
\end{document}

enter image description here

share|improve this question

2 Answers 2

up vote 6 down vote accepted

The following example, puts the header elements (left, centered, right) in a box and measures its width. If the width is zero, then the header rule is suppressed:

\documentclass{article}
\usepackage{filecontents}

\begin{filecontents}{mystyle.sty}
%% My package starts here
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mystyle}
\RequirePackage{fancyhdr}
\let\org@fancyhead\@fancyhead
\renewcommand*{\@fancyhead}[5]{%
  \sbox0{#2#3#4}%
  \ifdim\wd0=\z@
    \let\headrule\relax
  \fi
  \org@fancyhead{#1}{#2}{#3}{#4}{#5}%
}
\pagestyle{fancy}
\fancyhf{}
\endinput
%% And ends here
\end{filecontents}

\usepackage{mystyle}

\begin{document}
\section{My first section}

\newpage
\fancyhead[C]{Header is set}
\section{My next section}

\end{document}

Remarks:

  • The redefinition of \headrule is local for the current header, because LaTeX calls the header code inside a box/group.
share|improve this answer
    
Beautiful solution :) –  Sverre Mar 16 at 19:11

Something like this, perhaps:

\documentclass{article}
\usepackage{filecontents}

\begin{filecontents}{mystyle.sty}
%% My package starts here
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mystyle}
\usepackage{fancyhdr}
    \pagestyle{fancy}
    \fancyhf{}
    \makeatletter
    \AtBeginDocument{% don't make the comparison until the start of the document as the header may get specified later in the preamble
      \xdef\tempa{\f@ncyoch\f@ncyech\f@ncyorh\f@ncyerh\f@ncyolh\f@ncyelh}% get the value of the header parts
      \xdef\tempb{\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x}% value for comparison: contents of header parts if no content is specified
      \ifx\tempa\tempb% test to see if they are the same
        \renewcommand{\headrulewidth}{0pt}% if they are, the centre header is empty to set the rule width to 0pt
      \fi% otherwise, do nothing
    }
    \makeatother
\endinput
%% And ends here
\end{filecontents}

\usepackage{mystyle}
\fancyhead[C]{Woah! There's no ruler here!}
% \fancyhead[C]{}

\begin{document}
\section{My first section}
\end{document}

The code works by comparing the value of the header components (\f@ncyoch\f@ncyech\f@ncyorh\f@ncyerh\f@ncyolh\f@ncyelh) with the value of the header if it has no substantive contents (\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x\unhbox \voidb@x). If they are the same, it sets the rule width to 0pt. If they are different, it doesn't interfere.

The code makes 2 important assumptions. One is probably reasonable in most cases. The other is probably not.

  • The code assumes that you do not have an empty header on even pages, say, and a contentful one on odd pages. I take it this is a reasonable assumption in most cases.
  • The code either enables or disables the header rule for the entire document (or until you issue a command to change the setting) based on whether the header is empty or not at the beginning of the document. So it will not work if your configuration is like that in Heiko Oberdiek's example where the rule should not be active on the first page, for example, but should be on the next. Assuming that the header will either have content for the entire document or not have it for the entire document is probably not reasonable in most cases.

Header with rule

Commenting out the header line:

No header - no rule

share|improve this answer
    
Could you say a thing or two about what your code does? –  Sverre Mar 17 at 12:20
1  
@Sverre See edited version. I also modified the code slightly. However, Heiko Oberdiek's solution is superior and should be preferred in at least the vast majority of cases. EDIT: Probably all cases. –  cfr Mar 17 at 23:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.