2

I just want to have a horizontal rule at the top of the text frame, closed to the top margin. I am trying to know why this is not a trivial issue.

As I understand, LaTeX \rule command makes a filled box, placed where it is called, in horizontal mode processing.

By the other hand, the TeX primitive \hrule make a horizontal filled box (of \hsize lenght) in vertical mode processing.

First of all, I am not really sure of the second affirmation. But, if it's okay, then I have two questions:

1) Why TeX insert a blank space above the first hrule it when it is invoqued at the beginning of the document? And how to avoid it?

2) Why TeX hrule implies a reduction of the space between two baselines? And how to keep it?

\documentclass{article}
\usepackage{fullpage, showframe}

\begin{document}
\hrule
One line
\hrule
Another line
\end{document}

enter image description here

1
  • @MarcelKrüger, I have edited the question again. I hope the problem is clear now.
    – e_moro
    Jun 5, 2020 at 12:49

2 Answers 2

1

\hrule is black rectangle in vertical list. You can specify all three dimensions:

\hrule height1cm depth4mm width8cm \relax

or some dimen specification can be missing. If depth is missing then default is 0pt. If height is missing then default is 0.4 pt. If width is missing then the \hrule width is equal to most wide element in the vertical list. It is typically \hsize because you have typically a paragraph output in the vertical list (it has \hsize width). But if there is not paragraph output or the \hsize is changed for various paragraphs then the statement: \hrule has its width equal to \hsize is not true.

ad 1) The \topskip register. See egreg's answer.

ad 2) Reduction of baselines: the \baselineskip is applied in vertical list using \prevdepth value. It is the depth of previous box in the vertical list. But putting \hrule removes this \prevdepth value, so next line is added without vertical space immediately after \hrule. But you can keep the \prevdepth value and use it after \hrule is inserted:

first line
\par % end of praragraph, we are in vertical mode
\dimen0=\prevdepth % we keep the \prevdepth value
\hrule % or \hrule width \hsize if you want to be sure that the width is \hsize
\kern-0.4pt % return to the position before \hrule is inserted
\prevdepth=\dimen0 % restoring \prevdepth
second line

I suppose that you don't want to place the \hrule at various positions between lines. The solution above does not use fixed position but the \hrule placement depends on the depth of the previous line: it is placed below first line without space.

If you want to use fixed position independent of the depth of previous line then the code should be:

first line
\par % end of paragraph, we are in vertical mode
\dimen0=\prevdepth % we keep the \prevdepth value
\kern-\dimen0 % now, our position is at the baseline of the previous line 
\kern3pt % we want to insert space 3pt between baseline and \hrule
\hrule
\kern-3.4pt % now, the position is at the baseline of the previous line
\kern\dimen0 % now, the position is at the same place as immediately after \par
\prevdepth=\dimen0 % restoring \prevdepth value
second line
2
  • Satisfied with your explanation. Allow me one last detail: Since the fontsize does not correspond to any actual length in the document layout, I am unable to find a general expression to put \ hrule (you advance 3pt arbitrarily).
    – e_moro
    Jun 8, 2020 at 16:50
  • @e_moro Yes, 3pt was selected arbitrarily. More conceptual could be: plain TeX sets strut size to 8.5pt height and 3.5pt depth when 10/12 pt typesetting is initialized. So, if you have \baselineskip 12pt then shifting by 3.3pt is good choice (0.4pt thickness rule have its center at 3.5pt strut depth). If you have another \baselineskip, then you can select a proportionally scaled value to this 3.3 pt.
    – wipet
    Jun 8, 2020 at 17:26
2

You get a \vskip of amount \topskip minus the height of the rule, so 9.6pt, at the top of a page.

If you add \showoutput to your document, you see

..\vbox(550.0+0.0)x345.0, glue set 525.65497fil
...\write-{}
...\glue(\topskip) 9.6
...\rule(0.4+0.0)x*
...\glue(\parskip) 0.0 plus 1.0
...\hbox(6.94444+0.0)x345.0, glue set 293.33327fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/n/10 O
....\OT1/cmr/m/n/10 n
....\OT1/cmr/m/n/10 e
....\glue 3.33333 plus 1.66666 minus 1.11111
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 i
....\OT1/cmr/m/n/10 n
....\OT1/cmr/m/n/10 e
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\rule(0.4+0.0)x*
...\glue(\parskip) 0.0 plus 1.0
...\hbox(6.94444+0.0)x345.0, glue set 275.2499fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/n/10 A
....\OT1/cmr/m/n/10 n
....\OT1/cmr/m/n/10 o
....\OT1/cmr/m/n/10 t
....\OT1/cmr/m/n/10 h
....\OT1/cmr/m/n/10 e
....\OT1/cmr/m/n/10 r
....\glue 3.33333 plus 1.66666 minus 1.11111
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 i
....\OT1/cmr/m/n/10 n
....\OT1/cmr/m/n/10 e
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 30.0
..\hbox(0.0+0.0)x345.0

Do \vspace*{-\topskip} to kill it. You will see

...\glue(\topskip) 10.0
...\rule(0.0+0.0)x*
...\penalty 10000
...\glue -10.0

because now the height of the rule is not taken into account.

3
  • Ok, I see. So, setting \topskip=0pt could also be a valid solution?
    – e_moro
    Jun 5, 2020 at 13:09
  • @e_moro Depending on what you want to do.
    – egreg
    Jun 5, 2020 at 13:25
  • I suppose that \topskip=0pt deactivate the "top glue" for all the document. Anyway, after several test, I have reformulate the question.
    – e_moro
    Jun 5, 2020 at 16:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .