mirror of
https://github.com/servo/servo.git
synced 2025-09-25 06:10:08 +01:00
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:
parent
b73538a676
commit
16d2e030eb
6 changed files with 189 additions and 4 deletions
|
@ -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(
|
||||
|
|
52
tests/wpt/meta/MANIFEST.json
vendored
52
tests/wpt/meta/MANIFEST.json
vendored
|
@ -238242,6 +238242,58 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"position-sticky-bottom-004.html": [
|
||||
"7439c2795360da76b1448ab098942737cbcc8680",
|
||||
[
|
||||
null,
|
||||
[
|
||||
[
|
||||
"/css/reference/ref-filled-green-100px-square.xht",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"position-sticky-bottom-005.html": [
|
||||
"3d226132a854b0d63c59298e19a1d1f8dbf03536",
|
||||
[
|
||||
null,
|
||||
[
|
||||
[
|
||||
"/css/reference/ref-filled-green-100px-square.xht",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"position-sticky-bottom-006.html": [
|
||||
"675ade1fcbae7a7c5e5749ecfb3d2313f22ae9d1",
|
||||
[
|
||||
null,
|
||||
[
|
||||
[
|
||||
"/css/reference/ref-filled-green-100px-square.xht",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"position-sticky-bottom-007.html": [
|
||||
"f2648f1e003ac16d29c49be5f61f27a2097fe1b9",
|
||||
[
|
||||
null,
|
||||
[
|
||||
[
|
||||
"/css/reference/ref-filled-green-100px-square.xht",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"position-sticky-change-top.html": [
|
||||
"6a327ccd567818c2267d808a890796724384726e",
|
||||
[
|
||||
|
|
33
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-004.html
vendored
Normal file
33
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-004.html
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Position Test: sticky element with bottom offset</title>
|
||||
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-position/#stickypos-insets">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="assert" content="
|
||||
The static position of #sticky is outside (below) of its containing block.
|
||||
Sticky positioning doesn't force it to move up into the containing block.
|
||||
">
|
||||
|
||||
<style>
|
||||
#scroll-container {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: red;
|
||||
}
|
||||
#sticky {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="scroll-container">
|
||||
<div style="height: 100px; margin-top: -100px">
|
||||
<div style="height: 100px"></div>
|
||||
<div id="sticky"></div>
|
||||
</div>
|
||||
</div>
|
33
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-005.html
vendored
Normal file
33
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-005.html
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Position Test: sticky element with bottom offset</title>
|
||||
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-position/#stickypos-insets">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="assert" content="
|
||||
The static position of #sticky is outside (above) of its containing block.
|
||||
Sticky positioning doesn't force it to move down into the containing block.
|
||||
">
|
||||
|
||||
<style>
|
||||
#scroll-container {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: red;
|
||||
}
|
||||
#sticky {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="scroll-container">
|
||||
<div style="padding-top: 200px">
|
||||
<div style="margin-top: -200px"></div>
|
||||
<div id="sticky"></div>
|
||||
</div>
|
||||
</div>
|
31
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-006.html
vendored
Normal file
31
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-006.html
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Position Test: sticky element with bottom offset</title>
|
||||
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-position/#stickypos-insets">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="assert" content="
|
||||
The static position of #sticky is outside (above) of its nearest scrollport.
|
||||
Sticky positioning doesn't force it to move down into the scrollport.
|
||||
">
|
||||
|
||||
<style>
|
||||
#scroll-container {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
#sticky {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
height: 100px;
|
||||
background: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="scroll-container">
|
||||
<div style="margin-top: -100px"></div>
|
||||
<div id="sticky"></div>
|
||||
</div>
|
36
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-007.html
vendored
Normal file
36
tests/wpt/tests/css/css-position/sticky/position-sticky-bottom-007.html
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Position Test: sticky element with bottom offset</title>
|
||||
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-position/#stickypos-insets">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="assert" content="
|
||||
When the scroll container is scrolled to the top, then #sticky is visible.
|
||||
If we scroll 100px down, then #sticky should update its sticky offsets
|
||||
to still be visible.
|
||||
">
|
||||
|
||||
<style>
|
||||
#scroll-container {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: red;
|
||||
}
|
||||
#sticky {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="scroll-container">
|
||||
<div style="height: 500px"></div>
|
||||
<div id="sticky"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
scroller.scrollTop = 100;
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue