summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskobes <skobes@chromium.org>2016-03-25 14:22:23 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-25 21:23:43 +0000
commit54502dc10d4a4cf3be8d9fb89db3d2927c7bbaf9 (patch)
tree19942c89a202a6c04f8ab4aed50d0aa49aef8e24
parentdd768d54bd4a775b8b9f17819f1535ed643d8c8b (diff)
downloadchromium_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.cpp12
-rw-r--r--third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp40
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)