How can I add a line at the bottom of the header at an exact height?

I have this so far:

#set page(
  "a4",
  margin: (top: 25mm, x: 20mm, bottom: 10mm),
  header: [
    #place(right, dy: 4mm, link("www.example.com", image("logo.png", width: 25mm)))
    #line(length: 100%)
  ],
)

But I don’t know how to place the line exactly 25 mm from the top.
I’ve tried adjusting the line’s start and end positions, but whatever I do it won’t go below 17 mm.

What I want is to draw a line separating the header from the body precisely at that point. The same applies to the footer.

I also tried with grid and place, but no result.

This won’t work because of the header-ascent parameter of page. See Page Function – Typst Documentation

header-ascent
The amount the header is raised into the top margin.

Default: 30% + 0pt

Visual representation of what you are trying to do
#set rect(width: 100%, height: 100%, fill: aqua)

#let show-size = {
  layout(size => {
    [#calc.round(size.width.cm(), digits: 2) cm #sym.times #calc.round(size.height.cm(), digits: 2) cm.]
  })
}

#set page(
  "a4",
  margin: (top: 25mm, x: 20mm, bottom: 10mm),
  header: [#rect(show-size)],
  footer: [#rect(show-size)],
)
#rect(fill: gray)[What you are trying to use
#show-size]

#set rect(inset: 0pt)
#set page(
  header-ascent: 0cm,
  footer-descent: 0mm,
)
#rect(fill: gray)[The full page 
#show-size]

If you add

#set page(
  header-ascent: 0cm,
  ...
)

then you will have access to the full size of the header. Not that I recommend that approach.

You could consider using the background parameter of page instead of header.

#set page(
  "a4",
  margin: (top: 25mm, x: 20mm, bottom: 10mm),
  background: {
    place(top + left, dx: 25mm, line(
      // The red line is 25mm long, to visualize
      length: 25mm,
      angle: 90deg,
      stroke: red,
    ))
    place(top + left, dy: 25mm, line(length: 100%)) // This is the line you want
  },
)

And of course readjust your margins.

1 Like

If the image is in the correct spot, then semi-manually extend the line:

#set page(
  margin: (top: 25mm, bottom: 10mm, x: 20mm),
  header: {
    place(right, dy: 4mm, link("www.example.com", rect()))
    context place(dx: -page.margin.left, dy: 25mm, line(
      length: 100% + page.margin.left + page.margin.right,
    ))
  },
)

#lorem(50)

If not, then don’t suffer and use background like @vmartel08 suggested:

#set page(
  margin: (top: 25mm, bottom: 10mm, x: 20mm),
  background: {
    place(right, dy: 4mm, link("www.example.com", rect()))
    place(dy: 25mm, line(length: 100%))
  },
)

#lorem(50)

The stroke issue: Add support for inside/center/outside strokes (change stroke bounding box). Zero page margins issue · Issue #5741 · typst/typst · GitHub.

Where to put both is also a question of semantics. If they are meant to live within a header specifically, then it makes more sense to put it there, but always consider the implementation cost. It not always worth it, especially if the output is identical.

1 Like

Thank you both. Now the problem I have is how to create a gap between the line and the first line of text, something that must be applied in every page.

Just set the top margin to more than 25mm for the body. Or the header-ascent for the header.

Indeed, I was just playing with that now. Many thanks.

1 Like