diff --git a/crates/typst/src/layout/container.rs b/crates/typst/src/layout/container.rs index 996ef6c99..9fdef0be4 100644 --- a/crates/typst/src/layout/container.rs +++ b/crates/typst/src/layout/container.rs @@ -422,8 +422,6 @@ pub struct BlockElem { /// This is, by default, set on heading blocks to prevent orphaned headings /// at the bottom of the page. /// - /// Marking a block as sticky makes it unbreakable. - /// /// ```example /// >>> #set page(height: 140pt) /// // Disable stickiness of headings. diff --git a/crates/typst/src/layout/flow/collect.rs b/crates/typst/src/layout/flow/collect.rs index 9fc64f067..a477c3347 100644 --- a/crates/typst/src/layout/flow/collect.rs +++ b/crates/typst/src/layout/flow/collect.rs @@ -189,7 +189,7 @@ impl<'a> Collector<'a, '_, '_> { self.output.push(spacing(elem.above(styles))); - if !breakable || sticky || fr.is_some() { + if !breakable || fr.is_some() { self.output.push(Child::Single(self.boxed(SingleChild { align, sticky, @@ -203,6 +203,7 @@ impl<'a> Collector<'a, '_, '_> { let alone = self.children.len() == 1; self.output.push(Child::Multi(self.boxed(MultiChild { align, + sticky, alone, elem, styles, @@ -375,6 +376,7 @@ fn layout_single_impl( #[derive(Debug)] pub struct MultiChild<'a> { pub align: Axes, + pub sticky: bool, alone: bool, elem: &'a Packed, styles: StyleChain<'a>, diff --git a/crates/typst/src/layout/flow/distribute.rs b/crates/typst/src/layout/flow/distribute.rs index 65516ccd8..a30b71bac 100644 --- a/crates/typst/src/layout/flow/distribute.rs +++ b/crates/typst/src/layout/flow/distribute.rs @@ -247,7 +247,7 @@ impl<'a, 'b> Distributor<'a, 'b, '_, '_, '_> { // Lay out the block. let (frame, spill) = multi.layout(self.composer.engine, self.regions)?; - self.frame(frame, multi.align, false, true)?; + self.frame(frame, multi.align, multi.sticky, true)?; // If the block didn't fully fit into the current region, save it into // the `spill` and finish the region. @@ -292,9 +292,9 @@ impl<'a, 'b> Distributor<'a, 'b, '_, '_, '_> { breakable: bool, ) -> FlowResult<()> { if sticky { - // If the frame is sticky and we haven't remember a preceding sticky - // element, make a checkpoint which we can restore should we end on - // this sticky element. + // If the frame is sticky and we haven't remembered a preceding + // sticky element, make a checkpoint which we can restore should we + // end on this sticky element. if self.stickable && self.sticky.is_none() { self.sticky = Some(self.snapshot()); } diff --git a/tests/ref/block-sticky-breakable.png b/tests/ref/block-sticky-breakable.png new file mode 100644 index 000000000..91287a7e6 Binary files /dev/null and b/tests/ref/block-sticky-breakable.png differ diff --git a/tests/suite/layout/container.typ b/tests/suite/layout/container.typ index d054175a2..e13679675 100644 --- a/tests/suite/layout/container.typ +++ b/tests/suite/layout/container.typ @@ -180,6 +180,12 @@ A #colbreak() C +--- block-sticky-breakable --- +// Ensure that sticky blocks are still breakable. +#set page(height: 60pt) +#block(sticky: true, lines(4)) +E + --- box-clip-rect --- // Test box clipping with a rectangle Hello #box(width: 1em, height: 1em, clip: false)[#rect(width: 3em, height: 3em, fill: red)]