layout: Clamp sticky positioning offset bounds by zero (#39443)

Sticky positioning tries to keep an element visible within the nearest
scrollport. However, the element can't be offset to go beyond its
containing block. We implement this as offset bounds.

The problem was that, if the element would already be overflowing its
containing block before applying the sticky positioning, then we were
forcing it to move inside the containing block. That was wrong, and is
solved by flooring or ceiling the offset bounds by zero.

Testing: Adding new tests

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Oriol Brufau 2025-09-23 09:22:10 +02:00 committed by GitHub
parent b73538a676
commit 16d2e030eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 189 additions and 4 deletions

View file

@ -1558,12 +1558,12 @@ impl BoxFragment {
// This is the minimum negative offset and then the maximum positive offset. We just
// specify every edge, but if the corresponding margin is None, that offset has no effect.
let vertical_offset_bounds = wr::StickyOffsetBounds::new(
containing_block_rect.min.y - frame_rect.min.y,
containing_block_rect.max.y - frame_rect.max.y,
(containing_block_rect.min.y - frame_rect.min.y).min(0.),
(containing_block_rect.max.y - frame_rect.max.y).max(0.),
);
let horizontal_offset_bounds = wr::StickyOffsetBounds::new(
containing_block_rect.min.x - frame_rect.min.x,
containing_block_rect.max.x - frame_rect.max.x,
(containing_block_rect.min.x - frame_rect.min.x).min(0.),
(containing_block_rect.max.x - frame_rect.max.x).max(0.),
);
let margins = SideOffsets2D::new(