How to change the page header without causing a pagebreak?

How do I set the page header (empty) for the current page (when starting a chapter) without adding an extra empty page?

set page() always starts a new page. However, you can find out in the header what page you are on and whether a chapter starts there. If you want to e.g. not show headers on the page where a chapter begins, the package may be right for you:

PS: be sure to check out the question guidelines, maybe you can reformulate your post title as a question.

Ok it was less effort for me to get to these 2 lines for the header definition than to understand the hydra manual:

 let ch = query(selector(<chapter>).after(here()))
 if ch.len() > 0 and ch.first().location().page() == here().page() { return } // empty

(Then adding the <chapter> label to each chapter)
Can’t I just query the labels on the current page?

Not that I know of. I guess that may change in the future though.

If your chapters are headings, you can instead query heading.where(level: 1), that saves you assigning these labels manually.

1 Like

Yes, this solution is pretty short and works great:

#set page(height: 5cm)

#set page(header: context {
  let ch = query(selector(<chapter>).after(here()))
  if ch.len() > 0 {
    if ch.first().location().page() == here().page() { return }
  }
  "not empty"
})

#lorem(20)

= Heading 1

#lorem(50)

= Heading 2 <chapter>

#lorem(50)

= Heading 3

#lorem(50)

= Heading 4 <chapter>

#lorem(50)
Output

But if your chapters have a common name, then you can use heading names instead of labels, which means a cleaner document overall:

#set page(height: 5cm)

#set page(header: context {
  let headings = query(selector(heading).after(here()))
  if headings.len() > 0 {
    let h = headings.first()
    let is-on-this-page = h.location().page() == here().page()
    let contains-chapter-in-name = h.body.text.starts-with("Chapter")
    if is-on-this-page and contains-chapter-in-name { return }
  }
  "not empty"
})

#lorem(20)

= Heading 1

#lorem(50)

= Chapter 2

#lorem(50)

= Heading 3

#lorem(50)

= Chapter 4

#lorem(50)
Output

No, since selector doesn’t have such method: Selector Type – Typst Documentation. And you also can’t do heading.where(location: here()), but this won’t be useful, as this also would check the X and Y position on a page. Maybe something like heading.where(on-page: here()) would be better. If you want, you can create a feature request issue.

let is-on-this-page = ch.first().location().page() == here().page()
if ch.len() > 0 and is-on-this-page { return }

The first line is not evaluated before the len() > 0 test?
I think you don’t get an error only because you happen to have actual labels in the text.

The heading version can work as @SillyFreak said with a level-check:
ch = query(heading.where(level: 1).after(here()))

Oops, that was an oversight.

Hey there, could you shoot me DM or reply elaborating which parts of the manual were confusing so that I may improve them? :slight_smile:

If we knew a little more about your document and how the header looks otherwise, if chapters get their own title pages, etc. then we could perhaps help a little better.

1 Like

I guess you may probably mean the hydra manual and my further research lead me to that assumption. Almost every single sentence.

I just want empty headers on chapter begin which is totally normal.

Then hydra doesn’t seem like the right recommendation, but it does contain logic for this when displaying the current heading in the page header.

I can outline how hydra does it so you can adapt it for your use case. As there’s no way to find out if an element (like a heading) is the first on a page semantically, the only way to guess if it is, is to measure it’s position relative to the header.

This is what hydra does in order to skip pages where a heading is at the top of the page. The relevant source code is here and can be copied and used on it’s own. It boils down to recreating the page top margin from the current styles and check whether the y position of the heading you found on the current page matches this.

This comes with some caveats on 0.11.1 and before if you have heading show rules which add v(...) before your show rules, see here, the main workaround is to place those rules in blocks or by adding invisible content before to force the show rule to have a y position before the spacing added by v(...).

If I understand this correctly, you need detect if a chapter begins at the top of the page by measuring margins?
Then my two lines of code above are better anyway because I know which headings level starts a new page. And for other levels I don’t want it anyway wherever they occur.

Hey @huz, I went ahead and updated your post title to match our guidelines: How to post in the Questions category. Make sure your post title is something you’d ask to a friend about Typst. :wink: