How to pagebreak before an heading, only if a certain condition is achieved?

Hello and welcome!

If your error is

warning: layout did not converge within 5 attempts
 = hint: check if any states or queries are updating themselves

This is normal, do not panic.

Let’s start with a simple question: if your heading was to be before the pagebreak, do you think you would get the same error? The answer is no.

What you wrote diverges in an infinite loop:

  • You add a pagebreak if the heading is halfway through the page by comparing to the heading element’s y position
  • You add the heading itself.
  • Backtracking, the heading’s position has … changed!
  • Typst tries to resolve this layout, but cannot do it within 5 attempts, hence the error, and you probably don’t have the result you hoped for.

Now, how do you actually write this condition? You have to use an element that does not move with your pagebreak. The simplest way is to add a metadata element. By querying that element’s position instead, you make sure you don’t have any “loops” :slight_smile:

#show heading.where(level: 1, outlined: true): it => {
  let h1 = query(metadata.where(value: "foo").before(here()))  
  if h1.len() != 0 and h1.first().location().position().y > page.height * .5 {
    pagebreak()
  }
  it
}

= A

#lorem(500)

#metadata("foo")
= B

For additional reading, you might want to take a look at the following threads:

1 Like