зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1540203 - Tweak scroll anchor selection to allow to select everything but inline-fragmentable, non-text boxes. r=dholbert
Per the discussion in https://github.com/w3c/csswg-drafts/issues/4247. Differential Revision: https://phabricator.services.mozilla.com/D44647 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6e3f7f6bb1
Коммит
5906f23d74
|
@ -441,6 +441,13 @@ ScrollAnchorContainer::ExamineAnchorCandidate(nsIFrame* aFrame) const {
|
|||
return ExamineResult::Exclude;
|
||||
}
|
||||
|
||||
const bool isReplaced = aFrame->IsFrameOfType(nsIFrame::eReplaced);
|
||||
|
||||
const bool isNonReplacedInline =
|
||||
aFrame->StyleDisplay()->IsInlineInsideStyle() && !isReplaced;
|
||||
|
||||
const bool isAnonBox = aFrame->Style()->IsAnonBox();
|
||||
|
||||
// See if this frame could have its own anchor node. We could check
|
||||
// IsScrollFrame(), but that would miss nsListControlFrame which is not a
|
||||
// scroll frame, but still inherits from nsHTMLScrollFrame.
|
||||
|
@ -450,31 +457,24 @@ ScrollAnchorContainer::ExamineAnchorCandidate(nsIFrame* aFrame) const {
|
|||
// it's not clear how an anchor adjustment should apply to multiple scrollable
|
||||
// frames. Blink allows this to happen, but they're not sure why [1].
|
||||
//
|
||||
// We also don't allow scroll anchors to be selected inside of SVG as it uses
|
||||
// a different layout model than CSS, and the specification doesn't say it
|
||||
// should apply.
|
||||
// We also don't allow scroll anchors to be selected inside of replaced
|
||||
// elements (like <img>, <video>, <svg>...) as they behave atomically. SVG
|
||||
// uses a different layout model than CSS, and the specification doesn't say
|
||||
// it should apply anyway.
|
||||
//
|
||||
// [1] https://github.com/w3c/csswg-drafts/issues/3477
|
||||
bool canDescend = !scrollable && !aFrame->IsSVGOuterSVGFrame();
|
||||
const bool canDescend = !scrollable && !isReplaced;
|
||||
|
||||
// Check what kind of frame this is
|
||||
bool isBlockOutside = aFrame->IsBlockOutside();
|
||||
bool isAnonBox = aFrame->Style()->IsAnonBox() && !isText;
|
||||
bool isInlineOutside = aFrame->IsInlineOutside() && !isText;
|
||||
|
||||
// If the frame is anonymous or inline-outside, search its descendants for a
|
||||
// scroll anchor.
|
||||
if ((isAnonBox || isInlineOutside) && canDescend) {
|
||||
// Non-replaced inline boxes (including ruby frames) and anon boxes are not
|
||||
// acceptable anchors, so we descend if possible, or otherwise exclude them
|
||||
// altogether.
|
||||
if (!isText && (isNonReplacedInline || isAnonBox)) {
|
||||
ANCHOR_LOG(
|
||||
"\t\tSearching descendants of anon or inline box (a=%d, i=%d).\n",
|
||||
isAnonBox, isInlineOutside);
|
||||
return ExamineResult::PassThrough;
|
||||
}
|
||||
|
||||
// If the frame is not block-outside or a text node then exclude it.
|
||||
if (!isBlockOutside && !isText) {
|
||||
ANCHOR_LOG("\t\tExcluding non block-outside or text node (b=%d, t=%d).\n",
|
||||
isBlockOutside, isText);
|
||||
"\t\tSearching descendants of anon or non-replaced inline box (a=%d, i=%d).\n",
|
||||
isAnonBox, isNonReplacedInline);
|
||||
if (canDescend) {
|
||||
return ExamineResult::PassThrough;
|
||||
}
|
||||
return ExamineResult::Exclude;
|
||||
}
|
||||
|
||||
|
@ -494,15 +494,14 @@ ScrollAnchorContainer::ExamineAnchorCandidate(nsIFrame* aFrame) const {
|
|||
return ExamineResult::Exclude;
|
||||
}
|
||||
|
||||
// At this point, if canDescend is true, we should only have visible
|
||||
// non-anonymous frames that are either:
|
||||
// 1. block-outside
|
||||
// 2. text nodes
|
||||
// It's not clear what the scroll anchoring bounding rect is, for elements
|
||||
// fragmented in the block direction (e.g. across column or page breaks).
|
||||
//
|
||||
// It's not clear what the scroll anchoring bounding rect of elements that are
|
||||
// block-outside should be when they are fragmented. For text nodes that are
|
||||
// fragmented, it's specified that we need to consider the union of its line
|
||||
// boxes.
|
||||
// Inline-fragmented elements other than text shouldn't get here because of
|
||||
// the isNonReplacedInline check.
|
||||
//
|
||||
// For text nodes that are fragmented, it's specified that we need to consider
|
||||
// the union of its line boxes.
|
||||
//
|
||||
// So for text nodes we handle them by including the union of line boxes in
|
||||
// the bounding rect of the primary frame, and not selecting any
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Scroll Anchoring: Anchor node can be an image</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/#anchor-node-selection">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/4247">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1540203">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
body { height: 4000px }
|
||||
#spacer { height: 100px }
|
||||
img {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
<div id=spacer></div>
|
||||
<br><br>
|
||||
<img>
|
||||
<script>
|
||||
test(() => {
|
||||
document.scrollingElement.scrollTop = 150;
|
||||
document.querySelector("#spacer").style.height = "150px";
|
||||
assert_equals(document.scrollingElement.scrollTop, 200);
|
||||
}, "Anchor selection can select images");
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Scroll Anchoring: Anchor node can be an empty inline-block</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/#anchor-node-selection">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/4247">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1540203">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
body { height: 4000px }
|
||||
#ib1, #ib2 { display: inline-block; height: 100px; width: 100% }
|
||||
</style>
|
||||
<span id=ib1></span>
|
||||
<br><br>
|
||||
<span id=ib2></span>
|
||||
<script>
|
||||
|
||||
// Tests anchoring to an empty inline-block.
|
||||
|
||||
test(() => {
|
||||
document.scrollingElement.scrollTop = 150;
|
||||
document.querySelector("#ib1").style.height = "150px";
|
||||
assert_equals(document.scrollingElement.scrollTop, 200);
|
||||
}, "Anchor selection can select empty inline-blocks");
|
||||
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче