How can I use different page number locations on alternating pages?

How is it possible to place page numbers at the top left corners of odd pages and top right corners of even pages?

┌───────╥───────┐ ┌───────╥───────┐
│ 1     ║     2 │ │ 3     ║     4 │
│       ║       │ │       ║       │
│       ║       │ │       ║       │
│       ║       │ │       ║       │
└───────╨───────┘ └───────╨───────┘

Or maybe the other way around, which is in fact a more correct way to number pages according to book design traditions:

┌───────┐ ┌───────╥───────┐ ┌───────╥───────┐
│     1 │ │ 2     ║     3 │ │ 4     ║     5 │
│       │ │       ║       │ │       ║       │
│       │ │       ║       │ │       ║       │
│       │ │       ║       │ │       ║       │
└───────┘ └───────╨───────┘ └───────╨───────┘

( Page setup guide – Typst Documentation documentation page doesn’t seem to mention this trick. The closest thing I have found there is:

#set page(header: context {
  if counter(page).get().first() > 1 [
    ...
  ]
})

Which can probably be changed like “if page number is divisible by 2, then it is even; otherwise, it is odd”. But then, how to implement this if/else in code? )

#set page(height: auto)

// Starting from left:
// #set page(header: context {
//   let page = counter(page).get().first()
//   let body = if calc.odd(page) [odd ] else [even ] + str(page)
//   let alignment = if calc.odd(page) { left } else { right }
//   align(alignment, body)
// })

// Starting from right (book style):
#set page(header: context {
  let page = counter(page).get().first()
  let body = if calc.odd(page) [odd ] else [even ] + str(page)
  let alignment = if calc.odd(page) { right } else { left }
  align(alignment, body)
})

#range(5).map(_ => pagebreak()).join()

This can be simplified to:

#set page(header: context {
  let page = counter(page).get().first()
  align(if calc.odd(page) { right } else { left })[#page]
})

I have a feeling that this might be achieved in some even easier way, but nothing else comes to mind.

1 Like