Hello,
I want to make sure that the caption will always stick to its figure without having a pagebreak between them. Whenever the figure is a table, the table should be allowed to split over pages, but the caption should never.
As stated in Figure Function – Typst Documentation and Why won't this table in a figure break across pages? - #3 by PgBiel, you just need to make figure breakable with the show-set rule:
#show figure.where(kind: table): set block(breakable: true, sticky: true)
#v(21pt)
#v(1pt)
#figure(table(columns: 3, ..range(33).map(_ => lorem(15))), caption: "caption")
Additionally, since this makes caption split from table, probably because there is no default rule to prevent this, enabling block.sticky fixes that. Though technically, I think this should be better:
#show figure.where(kind: table): set block(breakable: true)
#show table: set block(sticky: true)
Because otherwise block after figure will stick to the figure, I think. But now any bare table also will be sticky, so a more accurate solution would be
#show figure.where(kind: table): set block(breakable: true)
#show figure.where(kind: table): it => {
show table: set block(sticky: true)
it
}
Though you won’t undo this nested show-set rule after you apply it. At some point you would be able to do show-show-set rule or something like that.
By default, since the figure is not breakable, the caption will never be put on a separate page, as caption and figure body are both in unbreakable block.
@Andrew’s solution probably works 99% of the time, but for some reason this figure will still have its caption on the next page:
#figure(
table(
columns: 1,
..range(40).map(_ => "test")
),
caption: "test"
)
Mentioned in Prevent page break directly between figure body and caption for breakable figures · Issue #5357 · typst/typst · GitHub.
This happens with raw blocks too:
// #show figure.where(kind: table): set block(breakable: true)
// #show figure.where(kind: table): it => {
// show table: set block(sticky: true)
// it
// }
// #figure(table(..range(40).map(_ => "test")), caption: "test")
#align(center, block(/* breakable: false, */ {
set block(spacing: 0pt)
block(sticky: true, range(40).map(_ => block(stroke: 1pt, inset: 5pt)[test]).join())
v(0.65em)
block[Table 1: test]
}))