The counter is resolved based on the logical order of things: The header is logically before the page content, which is followed by the footer. Thus, if you have a counter update within a page, it will be reflected in the footer, but not in the header.
However, there is an escape hatch: Typically, what you truly want is to reset the page counter between to pages. To do that, you can sandwich an update between two pagebreaks (with at least of them being weak
), and Typst will correctly understand that it’s supposed to happen in the empty void between. (Unfortunately, this behaviour is not properly documented.)
The following example demonstrates the feature:
#set page(
paper: "a8",
margin: 40pt,
header: context counter(page).display(),
footer: context counter(page).display(),
)
A
// Try uncommenting each of the pagebreaks in turn:
// #pagebreak()
#counter(page).update(5)
// #pagebreak(weak: true)
B
With this, you can fix the first problem of your page numbering (that numbers are off by one). The second part (which is not exhibited by your example) is more problematic: The final value will always corresponds to the page number at the very end of the document, not to the end of the “section”. There is no built-in feature for this at the moment, but it can be realized with a slightly more manual setup, which I’ve implemented below:
// Returns the page total of the current section.
#let reset = <__reset>
#let subtotal() = {
let loc = here()
let list = query(selector(reset).after(loc))
if list.len() > 0 {
counter(page).at(list.first().location()).first() - 1
} else {
counter(page).final().first()
}
}
// A section of content with reset page numbering.
//
// Leaves a marker we can query to find the subtotal page number.
// Resets the page counter in between the pages.
#let section(it) = {
pagebreak(weak: true)
[#metadata(none)#reset]
counter(page).update(1)
pagebreak(weak: true)
it
}
#let page-numbers = context numbering(
"1 / 1",
..counter(page).get(),
subtotal(),
)
#set page(
paper: "a8",
margin: 40pt,
// Show both in the header & footer to see the effect.
header: align(center, page-numbers),
footer: align(center, page-numbers),
)
#section([= A] + lorem(30))
#section([= B] + lorem(60))
#section([= C] + lorem(30))