Bug 1882091 - Use scrolled rect minus padding to contain sticky children. r=TYLin

I think this makes sense now that the padding is included in the
scrollable overflow area.

Differential Revision: https://phabricator.services.mozilla.com/D204354
This commit is contained in:
Emilio Cobos Álvarez 2024-03-13 16:16:42 +00:00
parent b5225f4bb4
commit 7ebfa77507
5 changed files with 227 additions and 3 deletions

View file

@ -186,12 +186,17 @@ void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
// Containing block limits for the position of aFrame relative to its parent.
// The margin box of the sticky element stays within the content box of the
// contaning-block element.
// containing-block element.
if (cbFrame == scrolledFrame) {
// cbFrame is the scrolledFrame, and it won't have continuations. Unlike the
// else clause, we consider scrollable overflow rect because and the union
// of its in-flow rects doesn't include the scrollable overflow area.
// else clause, we consider scrollable overflow rect because the union of
// its in-flow rects doesn't include the scrollable overflow area. We need
// to subtract the padding however, which _is_ included in the scrollable
// area, since we want the content box.
MOZ_ASSERT(cbFrame->GetUsedBorder() == nsMargin(),
"How did the ::-moz-scrolled-frame end up with border?");
*aContain = cbFrame->ScrollableOverflowRectRelativeToSelf();
aContain->Deflate(cbFrame->GetUsedPadding());
nsLayoutUtils::TransformRect(cbFrame, aFrame->GetParent(), *aContain);
} else {
*aContain = nsLayoutUtils::GetAllInFlowRectsUnion(

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.block {
position: relative;
width: 300px;
height: 210px;
padding: 10px;
padding-top: 0;
margin: 10px;
float: left;
background-color: #ddd;
}
.col {
width: 100px;
background-color: blue;
height: 210px;
}
.abspos {
position: absolute;
width: 10px;
height: 10px;
background-color: cyan;
top: 210px;
}
</style>
<div class="block">
<div class="col"></div>
<div class="abspos"></div>
</div>
<div class="block">
<div class="col"></div>
<div class="abspos"></div>
</div>

View file

@ -0,0 +1,73 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="help" href="https://drafts.csswg.org/css-position/#sticky-pos">
<link rel="help" href="https://bugzil.la/1882091">
<link rel="match" href="position-sticky-padding-001-ref.html">
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
.flex,
.block {
position: relative;
width: 300px;
height: 200px;
padding: 10px;
margin: 10px;
float: left;
overflow: auto;
scrollbar-width: none;
background-color: #ddd;
}
.flex {
display: flex;
flex-direction: row;
align-items: start;
justify-content: space-between;
}
.col {
width: 100px;
background-color: blue;
}
.col-1 {
position: sticky;
min-height: 300px;
top: 0;
}
.col-2 {
height: 20px;
align-self: start;
background-color: purple;
}
.block .col-2 {
float: right; /* Just make it visible */
}
.abspos {
position: absolute;
width: 10px;
height: 10px;
background-color: cyan;
top: 600px;
}
</style>
<div class="flex">
<div class="col col-1"></div>
<div class="col col-2"></div>
<div class="abspos"></div>
</div>
<div class="block">
<div class="col col-2"></div>
<div class="col col-1"></div>
<div class="abspos"></div>
</div>
<script>
onload = function() {
for (let e of document.querySelectorAll('.flex,.block')) {
e.scrollTop = 100000;
}
};
</script>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.block {
position: relative;
width: 210px;
height: 300px;
padding: 10px;
padding-left: 0;
margin: 10px;
float: left;
background-color: #ddd;
}
.row {
height: 100px;
width: 210px;
background-color: blue;
}
.abspos {
position: absolute;
width: 10px;
height: 10px;
background-color: cyan;
top: 0;
left: 210px;
}
</style>
<div class="block">
<div class="row"></div>
<div class="abspos"></div>
</div>
<div class="block">
<div class="row"></div>
<div class="abspos"></div>
</div>

View file

@ -0,0 +1,71 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="help" href="https://drafts.csswg.org/css-position/#sticky-pos">
<link rel="help" href="https://bugzil.la/1882091">
<link rel="match" href="position-sticky-padding-002-ref.html">
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
.flex,
.block {
position: relative;
width: 200px;
height: 300px;
padding: 10px;
margin: 10px;
float: left;
overflow: auto;
scrollbar-width: none;
background-color: #ddd;
}
.flex {
display: flex;
flex-direction: column;
align-items: start;
justify-content: space-between;
}
.row {
height: 100px;
background-color: blue;
}
.row-1 {
position: sticky;
min-width: 300px;
left: 0;
}
.row-2 {
width: 20px;
align-self: start;
background-color: purple;
}
.abspos {
position: absolute;
width: 10px;
height: 10px;
background-color: cyan;
left: 600px;
top: 0;
}
</style>
<div class="flex">
<div class="row row-1"></div>
<div class="row row-2"></div>
<div class="abspos"></div>
</div>
<div class="block">
<div class="row row-1"></div>
<div class="row row-2"></div>
<div class="abspos"></div>
</div>
<script>
onload = function() {
for (let e of document.querySelectorAll('.flex,.block')) {
e.scrollLeft = 100000;
}
};
</script>