diff options
author | skobes <skobes@chromium.org> | 2016-03-25 14:22:23 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-25 21:23:43 +0000 |
commit | 54502dc10d4a4cf3be8d9fb89db3d2927c7bbaf9 (patch) | |
tree | 19942c89a202a6c04f8ab4aed50d0aa49aef8e24 | |
parent | dd768d54bd4a775b8b9f17819f1535ed643d8c8b (diff) | |
download | chromium_src-54502dc10d4a4cf3be8d9fb89db3d2927c7bbaf9.zip chromium_src-54502dc10d4a4cf3be8d9fb89db3d2927c7bbaf9.tar.gz chromium_src-54502dc10d4a4cf3be8d9fb89db3d2927c7bbaf9.tar.bz2 |
Handle position:absolute candidates correctly in ScrollAnchor.
An absolute-positioned candidate should be considered only if it would
actually scroll with the scroller (otherwise the anchoring scroll will have no
effect on it).
BUG=594873
Review URL: https://codereview.chromium.org/1831993002
Cr-Commit-Position: refs/heads/master@{#383361}
-rw-r--r-- | third_party/WebKit/Source/core/layout/ScrollAnchor.cpp | 12 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp | 40 |
2 files changed, 51 insertions, 1 deletions
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp index ba2558b..7959b41 100644 --- a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp @@ -86,6 +86,16 @@ static LayoutPoint computeRelativeOffset(const LayoutObject* layoutObject, const return cornerPointOfRect(relativeBounds(layoutObject, scroller), corner); } +static bool candidateMovesWithScroller(const LayoutObject* candidate, const ScrollableArea* scroller) +{ + if (candidate->style() && candidate->style()->hasViewportConstrainedPosition()) + return false; + + bool skippedByContainerLookup = false; + candidate->container(scrollerLayoutBox(scroller), &skippedByContainerLookup); + return !skippedByContainerLookup; +} + ScrollAnchor::ExamineResult ScrollAnchor::examine(const LayoutObject* candidate) const { if (candidate->isLayoutInline()) @@ -94,7 +104,7 @@ ScrollAnchor::ExamineResult ScrollAnchor::examine(const LayoutObject* candidate) if (!candidate->isText() && !candidate->isBox()) return ExamineResult(Skip); - if (candidate->style() && candidate->style()->hasViewportConstrainedPosition()) + if (!candidateMovesWithScroller(candidate, m_scroller)) return ExamineResult(Skip); LayoutRect candidateRect = relativeBounds(candidate, m_scroller); diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp index 0f7a5e0..f52e831 100644 --- a/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp @@ -180,6 +180,46 @@ TEST_F(ScrollAnchorTest, ExcludeFixedPosition) scrollAnchor(layoutViewport()).anchorObject()); } +TEST_F(ScrollAnchorTest, ExcludeAbsolutePosition) +{ + setBodyInnerHTML( + "<style>" + " body { margin: 0; }" + " #scroller { overflow: scroll; width: 500px; height: 400px; }" + " #space { height: 1000px; }" + " #abs {" + " position: absolute; background-color: red;" + " left: 200px; top: 100px; width: 100px; height: 100px;" + " }" + " #rel {" + " position: relative; background-color: green;" + " left: 50px; top: 100px; width: 100px; height: 75px;" + " }" + "</style>" + "<div id='scroller'><div id='space'>" + " <div id='abs'></div>" + " <div id='rel'></div>" + "</div></div>"); + + Element* scrollerElement = document().getElementById("scroller"); + ScrollableArea* scroller = scrollerForElement(scrollerElement); + Element* absPos = document().getElementById("abs"); + Element* relPos = document().getElementById("rel"); + + scroller->scrollBy(DoubleSize(0, 25), UserScroll); + setHeight(relPos, 100); + + // When the scroller is position:static, the anchor cannot be position:absolute. + EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject()); + + scrollerElement->setAttribute(HTMLNames::styleAttr, "position: relative"); + scroller->scrollBy(DoubleSize(0, 25), UserScroll); + setHeight(relPos, 125); + + // When the scroller is position:relative, the anchor may be position:absolute. + EXPECT_EQ(absPos->layoutObject(), scrollAnchor(scroller).anchorObject()); +} + class ScrollAnchorCornerTest : public ScrollAnchorTest { protected: void checkCorner(const AtomicString& id, Corner corner, DoublePoint startPos, DoubleSize expectedAdjustment) |