summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target')
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html74
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-display-toggled.tentative.html125
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-nested-container.tentative.html230
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-root.tentative.html63
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-rtl.tentative.html63
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation-inner-frame.html42
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation.tentative.html60
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation-inner-frame.html48
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation.tentative.html34
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-snap.tentative.html79
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start-root.tentative.html66
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start.tentative.html75
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation-target.html83
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation.tentative.html49
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-user-programmatic-scroll.tentative.html125
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target.tentative.html98
-rw-r--r--testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/stash.py27
17 files changed, 1341 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html
new file mode 100644
index 0000000000..6b133dea7d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/dom/events/scrolling/scroll_support.js"></script>
+ </head>
+ <body>
+ <style>
+ #space {
+ width: 1000px;
+ height: 1000px;
+ border: solid 1px red;
+ }
+ #scroller {
+ width: 400px;
+ height: 400px;
+ overflow: hidden;
+ border: solid 1px blue;
+ position: absolute;
+ }
+ #target {
+ width: 100px;
+ height: 100px;
+ background-color: pink;
+ scroll-start-target: auto auto;
+ position: absolute;
+ top: 400px;
+ left: 400px;
+ }
+ </style>
+ <div id="scroller">
+ <div id="space"></div>
+ <div id="target"></div>
+ </div>
+ <script>
+ promise_test(async (t) => {
+ await waitForCompositorCommit();
+
+ assert_equals(scroller.scrollTop, 400,
+ "scroller is vertically scrolled to target");
+ assert_equals(scroller.scrollLeft, 400,
+ "scroller is horizontally scrolled to target");
+
+ target.style.scrollSnapAlign = "center";
+ await waitForCompositorCommit();
+
+ assert_equals(scroller.scrollTop, 250,
+ "scroller is vertically aligned to target's center");
+ assert_equals(scroller.scrollLeft, 250,
+ "scroller is horizontally aligned to target's center");
+
+ target.style.scrollSnapAlign = "end";
+ await waitForCompositorCommit();
+
+ assert_equals(scroller.scrollTop, 100,
+ "scroller is vertically aligned to target's bottom");
+ assert_equals(scroller.scrollLeft, 100,
+ "scroller is horizontally aligned to target's right");
+
+ target.style.scrollSnapAlign = "start";
+ await waitForCompositorCommit();
+
+ assert_equals(scroller.scrollTop, 400,
+ "scroller is vertically aligned to target's top");
+ assert_equals(scroller.scrollLeft, 400,
+ "scroller is horizontally aligned to target's left");
+ }, "scroll-start-target aligns with scroll-snap-align");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-display-toggled.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-display-toggled.tentative.html
new file mode 100644
index 0000000000..527d750267
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-display-toggled.tentative.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <style>
+ #space-filler {
+ width: 500px;
+ height: 500px;
+ border: solid 1px red;
+ }
+ #outer-container {
+ width: 400px;
+ height: 400px;
+ overflow: scroll;
+ border: solid 2px blue;
+ }
+ #inner-container {
+ top: 20px;
+ left: 20px;
+ width: 300px;
+ height: 300px;
+ overflow: scroll;
+ position: relative;
+ border: solid 2px black;
+ }
+ #target {
+ width: 100px;
+ height: 100px;
+ background-color: pink;
+ scroll-start-target: auto auto;
+ }
+ </style>
+ <div id="outer-container">
+ <div id="inner-container">
+ <div id="space-filler"></div>
+ <div id="target">
+ </div>
+ </div>
+ </div>
+ <script>
+ let outer_scroller = document.getElementById("outer-container");
+ let inner_scroller = document.getElementById("inner-container");
+ let space_filler = document.getElementById("space-filler");
+ let target = document.getElementById("target");
+
+ const target_height = target.getBoundingClientRect().height;
+ const space_filler_height = space_filler.getBoundingClientRect().height;
+ const total_content_height = target_height + space_filler_height;
+
+ async function resetDisplay() {
+ return new Promise((resolve) => {
+ if (getComputedStyle(outer_scroller).display == "block" &&
+ getComputedStyle(inner_scroller).display == "block" &&
+ getComputedStyle(target).display == "block") {
+ resolve();
+ } else {
+ outer_scroller.style.display = "block";
+ inner_scroller.style.display = "block";
+ target.style.display = "block";
+ requestAnimationFrame(async () => {
+ await resetDisplay();
+ resolve();
+ });
+ }
+ });
+ }
+
+ async function waitForDisplay(element, display) {
+ return new Promise((resolve) => {
+ if (getComputedStyle(element).display == display) {
+ resolve();
+ } else {
+ requestAnimationFrame(async () => {
+ await waitForDisplay(element, display);
+ resolve();
+ })
+ }
+ });
+ }
+
+ promise_test(async (t) => {
+ await resetDisplay();
+ let initial_expected_scroll_top =
+ total_content_height - inner_scroller.clientHeight;
+ assert_equals(inner_scroller.scrollTop, initial_expected_scroll_top,
+ "inner-scroller is scrolled to scroll-start-target");
+
+ let display_promise = waitForDisplay(target, "none");
+ target.style.display = "none";
+ await display_promise;
+
+ let final_expected_scroll_top = initial_expected_scroll_top - target_height;
+ assert_equals(inner_scroller.scrollTop, final_expected_scroll_top,
+ "inner scroller is clamped to updated scroll range");
+ }, "display:block scroll-start-target becomes display: none");
+
+ promise_test(async (t) => {
+ await resetDisplay();
+ let initial_expected_scroll_top =
+ total_content_height - inner_scroller.clientHeight;
+ assert_equals(inner_scroller.scrollTop, initial_expected_scroll_top,
+ "inner-scroller is scrolled to scroll-start-target");
+
+ let display_promise = waitForDisplay(target, "none");
+ target.style.display = "none";
+ await display_promise;
+ assert_equals(inner_scroller.scrollTop,
+ initial_expected_scroll_top - target_height,
+ "inner scroller is clamped to updated scroll range");
+
+ display_promise = waitForDisplay(target, "block");
+ target.style.display = "block";
+ await display_promise;
+ assert_equals(inner_scroller.scrollTop, initial_expected_scroll_top,
+ "inner scroller is updated as scroll-start-target reappears");
+ }, "display:none scroll-start-target becomes display: block");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-nested-container.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-nested-container.tentative.html
new file mode 100644
index 0000000000..b84803c941
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-nested-container.tentative.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script src="/dom/events/scrolling/scroll_support.js"></script>
+ </head>
+ <body>
+ <style>
+ #space-filler {
+ width: 500px;
+ height: 500px;
+ background-color: green;
+ }
+ #outer-container {
+ width: 400px;
+ height: 400px;
+ overflow: scroll;
+ background-color: yellow;
+ }
+ #inner-container {
+ top: 20px;
+ left: 20px;
+ width: 300px;
+ height: 300px;
+ overflow: visible;
+ position: relative;
+ background-color: blue;
+ }
+ #target {
+ width: 100px;
+ height: 100px;
+ background-color: pink;
+ scroll-start-target: auto auto;
+ }
+ </style>
+ <div id="outer-container">
+ <div id="space-filler"></div>
+ <div id="inner-container">
+ <div id="space-filler"></div>
+ <div id="target">
+ </div>
+ </div>
+ </div>
+ <script>
+ let outer_container = document.getElementById("outer-container");
+ let inner_container = document.getElementById("inner-container");
+ let space_filler = document.getElementById("space-filler");
+ let target = document.getElementById("target");
+
+ const inner_scroller_top_offset = 20;
+ const target_height = target.getBoundingClientRect().height;
+ const space_filler_height = space_filler.getBoundingClientRect().height;
+ const inner_content_height = target_height + space_filler_height;
+ const inner_container_height = inner_container.getBoundingClientRect().height;
+
+ async function resetDisplay() {
+ return new Promise((resolve) => {
+ if (getComputedStyle(outer_container).display == "block" &&
+ getComputedStyle(inner_container).display == "block" &&
+ getComputedStyle(target).display == "block") {
+ resolve();
+ } else {
+ outer_container.style.display = "block";
+ inner_container.style.display = "block";
+ target.style.display = "block";
+ requestAnimationFrame(async () => {
+ await resetDisplay();
+ resolve();
+ });
+ }
+ });
+ }
+
+ async function waitForCSSProperty(element, property, value) {
+ return new Promise((resolve) => {
+ if (getComputedStyle(element)[property] == value) {
+ resolve();
+ } else {
+ requestAnimationFrame(async () => {
+ await waitForCSSProperty(element, property, value);
+ resolve();
+ })
+ }
+ });
+ }
+
+ async function waitForDisplay(element, value) {
+ return waitForCSSProperty(element, "display", value);
+ }
+
+ async function waitForOverflow(element, value) {
+ return waitForCSSProperty(element, "overflow", value);
+ }
+
+ let initial_expected_scroll_top = space_filler_height +
+ inner_scroller_top_offset + inner_content_height -
+ outer_container.clientHeight;
+ promise_test(async (t) => {
+ await resetDisplay();
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-container is scrolled to scroll-start-target");
+
+ inner_container.style.display = "none";
+ await waitForDisplay(inner_container, "none");
+
+ assert_equals(outer_container.scrollTop,
+ space_filler_height - outer_container.clientHeight,
+ "outer-container has no content to scroll");
+
+ inner_container.style.display = "block";
+ await waitForDisplay(inner_container, "block");
+
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-scroller is updated as scroll-start-target reappears");
+ }, "display:none scroll-start-target becomes display:block");
+
+ promise_test(async (t) => {
+ await waitForCompositorCommit();
+ await resetDisplay();
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-container is scrolled to scroll-start-target");
+
+ inner_container.style.overflow = "scroll";
+ await waitForOverflow(inner_container, "scroll");
+
+ // inner-container has become a scroller and should be scrolled to
+ // scroll-start-target.
+ assert_equals(inner_container.scrollTop,
+ inner_content_height - inner_container.clientHeight,
+ "inner-container is fully scrolled to target");
+ // outer-container should be adjusted to its new max scroll offset.
+ const scrollbar_width = outer_container.offsetHeight -
+ outer_container.clientHeight;
+ assert_equals(outer_container.scrollTop,
+ space_filler_height + inner_scroller_top_offset +
+ inner_container_height - outer_container.clientHeight,
+ "outer-container's overflowing content is only its direct " +
+ "children");
+
+ inner_container.style.overflow = "visible";
+ await waitForOverflow(inner_container, "visible");
+
+ assert_equals(inner_container.scrollTop, 0,
+ "inner-container is no longer a scroll container");
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-scroller is the scroll container for target once again");
+ }, "intermediate overflow:visible container becomes overflow:scroll");
+
+ promise_test(async (t) => {
+ // This test verifies that:
+ // 1. when both the child and grandchild are scroll-start-targets, the
+ // grandchild wins/is scrolled to.
+ // 2. if/when the grandchild stops being a scroll-start-target, the
+ // child (inner container) is scrolled to.
+ await waitForCompositorCommit();
+ await resetDisplay();
+ t.add_cleanup(async () => {
+ target.style.scrollStartTarget = "auto auto";
+ await waitForCSSProperty(target, "scroll-start-target", "auto");
+ });
+
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-container is scrolled to scroll-start-target");
+ // Make the inner container a scroll-start-target.
+ inner_container.style.scrollStartTarget = "auto auto";
+ await waitForCSSProperty(inner_container, "scroll-start-target", "auto");
+
+ // The inner container has overflow: visible, so it's not the scroll
+ // container of target.
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-container is still scrolled to inner scroll-start-target");
+
+ // Make target no longer a scroll-start-target. The outer container's
+ // scroll-start-target should now be the inner container.
+ target.style.scrollStartTarget = "none none";
+ await waitForCSSProperty(target, "scroll-start-target", "none");
+ assert_equals(outer_container.scrollTop,
+ space_filler_height + inner_scroller_top_offset,
+ "outer-container is scrolled to inner-container");
+ }, "inner scroll-start-target takes precedence over outer");
+
+ promise_test(async (t) => {
+ // This test verifies that a child which is a scroller, is a
+ // scroll-start-target, and has a scroll-start-target is scrolled to by
+ // its scrolling container, and also scrolls to its own
+ // scroll-start-target.
+ await waitForCompositorCommit();
+ await resetDisplay();
+ t.add_cleanup(async () => {
+ inner_container.style.overflow = "visible";
+ inner_container.style.scrollStartTarget = "none none";
+ await waitForCSSProperty(inner_container, "overflow",
+ "visible");
+ await waitForCSSProperty(inner_container, "scroll-start-target",
+ "none");
+ });
+
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-container is scrolled to scroll-start-target");
+
+ // Make the inner container a scroll-start-target.
+ inner_container.style.scrollStartTarget = "auto auto";
+ await waitForCSSProperty(inner_container, "scroll-start-target", "auto");
+
+ assert_equals(outer_container.scrollTop, initial_expected_scroll_top,
+ "outer-container is still scrolled to inner scroll-start-target");
+
+ // Make the inner container a scroller.
+ inner_container.style.overflow = "scroll";
+ await waitForOverflow(inner_container, "scroll");
+
+ assert_equals(outer_container.scrollTop,
+ space_filler_height + inner_scroller_top_offset +
+ inner_container.offsetHeight - outer_container.clientHeight,
+ "outer-container is scrolled to the inner container");
+ assert_equals(inner_container.scrollTop,
+ space_filler_height + target.offsetHeight -
+ inner_container.clientHeight,
+ "inner-container is scrolled to target");
+ }, "scroll containers can also be scroll-start-targets");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-root.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-root.tentative.html
new file mode 100644
index 0000000000..f2af38bbab
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-root.tentative.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <style>
+ .spacer {
+ width: 200vw;
+ height: 200vh;
+ }
+
+ .box {
+ position: absolute;
+ width: 60vw;
+ height: 60vh;
+ }
+
+ .top_left {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .center {
+ top: 60vh;
+ left: 60vw;
+ background-color: purple;
+ scroll-start-target: auto auto;
+ }
+
+ .bottom_right {
+ top: 120vh;
+ left: 120vw;
+ background-color: yellow;
+ }
+ </style>
+ <div class="spacer"></div>
+ <div class="top_left box" id="top_left_box"></div>
+ <div class="center box" id="centerbox"></div>
+ <div class="bottom_right box"></div>
+ <script>
+ test((t) => {
+ let scroller = document.scrollingElement;
+ let top_left_box = document.getElementById("top_left_box");
+
+ const expected_scroll_top = top_left_box.getBoundingClientRect().height;
+ const expected_scroll_left = top_left_box.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+ });
+ </script>
+</body>
+
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-rtl.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-rtl.tentative.html
new file mode 100644
index 0000000000..5a2fa0a93c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-rtl.tentative.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <style>
+ #scroller {
+ height: 500px;
+ width: 500px;
+ display: block;
+ overflow: scroll;
+ writing-mode: vertical-rl;
+ }
+
+ .box {
+ position: relative;
+ width: 60%;
+ height: 60%;
+ }
+
+ .top_right {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .center {
+ top: 60%;
+ background-color: purple;
+ scroll-start-target: auto auto;
+ }
+
+ .bottom_left {
+ top: 120%;
+ background-color: yellow;
+ }
+ </style>
+ <div id="scroller">
+ <div class="top_right box" id="box1"></div>
+ <div class="center box" id="box2"></div>
+ <div class="bottom_left box" id="box3"></div>
+ </div>
+ <script>
+ let initial_expected_scroll_top = box1.getBoundingClientRect().height;
+ let initial_expected_scroll_left = -box1.getBoundingClientRect().width;
+
+ test((t) => {
+ assert_equals(scroller.scrollTop, initial_expected_scroll_top,
+ "scroller is vertically scrolled to scroll-start-target");
+ assert_equals(scroller.scrollLeft, initial_expected_scroll_left,
+ "scroller is horizontally scrolled to scroll-start-target");
+ }, "scroll-start-target reflects vertical rtl writing mode.");
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation-inner-frame.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation-inner-frame.html
new file mode 100644
index 0000000000..bea0525ecd
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation-inner-frame.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+</head>
+
+<body>
+ <style>
+ :root, body {
+ margin: 0px;
+ }
+
+ #spacer {
+ height: 100vh;
+ width: 100px;
+ }
+
+ #top_box {
+ width: 100px;
+ height: 60vh;
+ background-color: red;
+ }
+ #middle_box {
+ width: 100px;
+ height: 60vh;
+ scroll-start-target: auto auto;
+ background-color: purple;
+ }
+ #bottom_box {
+ width: 100px;
+ height: 60vh;
+ background-color: yellow;
+ }
+ </style>
+ <div id="top_box"><a id="anchor_target_link" href="#anchor_target">Anchor Link</a></div>
+ <div id="middle_box"></div>
+ <div id="bottom_box"></div>
+ <div id="spacer"></div>
+ <div id="anchor_target">Anchor Target</div>
+</body>
+
+</html>
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation.tentative.html
new file mode 100644
index 0000000000..bc5b75f75f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-anchor-navigation.tentative.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target interaction with anchor navigation</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script src="/html/browsers/browsing-the-web/resources/helpers.js"></script>
+ <script src="/dom/events/scrolling/scroll_support.js"></script>
+</head>
+
+<body>
+ <iframe id="frame" src="scroll-start-target-with-anchor-navigation-inner-frame.html" onload="runTest()"></iframe>
+ <script>
+ function runTest() {
+ promise_test(async (t) => {
+ await waitForCompositorCommit();
+ let scroller = frame.contentDocument.scrollingElement;
+ // anchor_target is at the bottom of the frame so the frame should be
+ // fully scrolled down to bring it into view.
+ let anchor_target_scrolltop = scroller.scrollHeight - scroller.clientHeight;
+ let anchor_target_link = frame.contentDocument.getElementById("anchor_target_link");
+
+ // Expect scroll offset of 100px per scroll-start.
+ const scroll_start_target_top = 0.6 * frame.contentWindow.innerHeight;
+ assert_equals(scroller.scrollTop, scroll_start_target_top,
+ "scroll-start-target sets initial scroll offset");
+
+ // Scroll away from start position.
+ scroller.scrollTop = 200;
+ assert_equals(scroller.scrollTop, 200,
+ "scrolled away from scroll-start-target");
+
+ anchor_target_link.click();
+ await waitForHashchange(frame.contentWindow);
+ assert_equals(frame.contentWindow.location.hash, "#anchor_target",
+ "clicking anchor link navigates to target");
+
+ // Expect page to be fully scrolled as anchor_target is at the bottom of
+ // the document.
+ assert_equals(scroller.scrollTop, anchor_target_scrolltop,
+ "anchor navigation sets scroll offset");
+
+ frame.contentWindow.history.back();
+ await waitForHashchange(frame.contentWindow);
+ assert_equals(frame.contentWindow.location.hash, "");
+
+ assert_equals(scroller.scrollTop, 200,
+ "scroller returns to previous scroll position, not " +
+ "scroll-start-target");
+ }, "scroll-start-target does not override anchor navigation.");
+ }
+ </script>
+</body>
+
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation-inner-frame.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation-inner-frame.html
new file mode 100644
index 0000000000..9bf77363d3
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation-inner-frame.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+</head>
+
+<body>
+ <style>
+ :root {
+ margin: 0px;
+ }
+
+ #spacer {
+ height: 100vh;
+ width: 100px;
+ }
+
+ #top_box {
+ width: 100px;
+ height: 60vh;
+ background-color: blue;
+ }
+ #middle_box {
+ width: 100px;
+ height: 60vh;
+ scroll-start-target: auto auto;
+ background-color: purple;
+ }
+ #bottom_box {
+ width: 100px;
+ height: 60vh;
+ background-color: yellow;
+ }
+
+ #fragment_target {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+ </style>
+ <div id="top_box"></div>
+ <div id="middle_box"></div>
+ <div id="bottom_box"></div>
+ <div id="spacer"></div>
+ <div id="fragment_target">Fragment Target</div>
+</body>
+
+</html>
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation.tentative.html
new file mode 100644
index 0000000000..2d291c2ef9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-hash-fragment-navigation.tentative.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target interaction with fragment-navigation</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <iframe id="frame" src="scroll-start-target-with-fragment-navigation-inner-frame.html#fragment_target"
+ onload="runTest()"></iframe>
+ <script>
+ function runTest() {
+ test((t) => {
+ let scroller = frame.contentDocument.scrollingElement;
+ // fragment_target is at the bottom of the frame so the frame should be
+ // fully scrolled down to bring it into view (despite middle_box being
+ // the scroll-start-target).
+ let expected_scroll_top = scroller.scrollHeight - scroller.clientHeight;
+ // The scroll-start-target is just below top_box which has a height of
+ // 60vh.
+ const scroll_start_target_top = 0.6 * frame.contentWindow.innerHeight;
+
+ assert_equals(frame.contentWindow.location.hash, "#fragment_target");
+ assert_not_equals(scroll_start_target_top, expected_scroll_top);
+ assert_equals(frame.contentDocument.scrollingElement.scrollTop,
+ expected_scroll_top);
+ }, "scroll-start-target does not override hash fragment navigation");
+ }
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-snap.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-snap.tentative.html
new file mode 100644
index 0000000000..9cb66c01fc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-snap.tentative.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <style>
+ .spacer {
+ width: 1000px;
+ height: 1000px;
+ }
+
+ .scroller {
+ width: 300px;
+ height: 300px;
+ border: solid 1px black;
+ overflow: scroll;
+ margin: 0px;
+ position: absolute;
+ scroll-snap-type: y mandatory;
+ }
+
+ .box {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+
+ .top_left {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .center {
+ top: 200px;
+ left: 200px;
+ background-color: purple;
+ scroll-start-target: auto auto;
+ }
+
+ .bottom_right {
+ top: 400px;
+ left: 400px;
+ background-color: yellow;
+ /* Expect scroller to snap to the top and left border of the bottom right div. */
+ scroll-snap-align: start start;
+ }
+ </style>
+ <div class="scroller" id="scroller">
+ <div class="spacer"></div>
+ <div class="top_left box" id="top_left_box"></div>
+ <div class="center box" id="centerbox"></div>
+ <div class="bottom_right box"></div>
+ </div>
+ <script>
+ test((t) => {
+ let scroller = document.getElementById("scroller");
+ let top_left_box = document.getElementById("top_left_box");
+ let center_box = document.getElementById("center_box");
+
+ const expected_scroll_top = top_left_box.getBoundingClientRect().height +
+ centerbox.getBoundingClientRect().height;
+ const expected_scroll_left = top_left_box.getBoundingClientRect().width;
+ centerbox.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+ });
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start-root.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start-root.tentative.html
new file mode 100644
index 0000000000..af99595f25
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start-root.tentative.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <style>
+ :root {
+ scroll-start: end end;
+ }
+
+ .spacer {
+ width: 200vw;
+ height: 200vh;
+ }
+
+ .box {
+ position: absolute;
+ width: 60vw;
+ height: 60vh;
+ }
+
+ .top_left {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .center {
+ top: 60vh;
+ left: 60vw;
+ background-color: purple;
+ scroll-start-target: auto auto;
+ }
+
+ .bottom_right {
+ top: 120vh;
+ left: 120vw;
+ background-color: yellow;
+ }
+ </style>
+ <div class="spacer"></div>
+ <div class="top_left box" id="top_left_box"></div>
+ <div class="center box" id="centerbox"></div>
+ <div class="bottom_right box"></div>
+ <script>
+ test((t) => {
+ let scroller = document.scrollingElement;
+ let top_left_box = document.getElementById("top_left_box");
+
+ const expected_scroll_top = top_left_box.getBoundingClientRect().height;
+ const expected_scroll_left = top_left_box.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+ });
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start.tentative.html
new file mode 100644
index 0000000000..a37c831288
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-scroll-start.tentative.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <style>
+ .spacer {
+ width: 1000px;
+ height: 1000px;
+ }
+
+ .scroller {
+ width: 300px;
+ height: 300px;
+ border: solid 1px black;
+ overflow: scroll;
+ margin: 0px;
+ position: absolute;
+ scroll-start: end end;
+ /* This should be overriden by scroll-start-target. */
+ }
+
+ .box {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+
+ .top_left {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .center {
+ top: 200px;
+ left: 200px;
+ background-color: purple;
+ scroll-start-target: auto auto;
+ }
+
+ .bottom_right {
+ top: 400px;
+ left: 400px;
+ background-color: yellow;
+ }
+ </style>
+ <div class="scroller" id="scroller">
+ <div class="spacer"></div>
+ <div class="top_left box" id="top_left_box"></div>
+ <div class="center box" id="centerbox"></div>
+ <div class="bottom_right box"></div>
+ </div>
+ <script>
+ test((t) => {
+ let scroller = document.getElementById("scroller");
+ let top_left_box = document.getElementById("top_left_box");
+
+ const expected_scroll_top = top_left_box.getBoundingClientRect().height;
+ const expected_scroll_left = top_left_box.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+ });
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation-target.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation-target.html
new file mode 100644
index 0000000000..da53e7a566
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation-target.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+
+<body>
+ <style>
+ :root {
+ margin: 0px;
+ }
+
+ #spacer {
+ height: 100vh;
+ width: 100px;
+ }
+
+ #top_box {
+ width: 100px;
+ height: 60vh;
+ background-color: blue;
+ }
+ #middle_box {
+ width: 100px;
+ height: 60vh;
+ scroll-start-target: auto auto;
+ background-color: purple;
+ }
+ #bottom_box {
+ width: 100px;
+ height: 60vh;
+ background-color: yellow;
+ }
+
+ #fragment_target {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+ </style>
+ <div id="top_box"></div>
+ <div id="middle_box"></div>
+ <div id="bottom_box"></div>
+ <div id="spacer"></div>
+ <div id="fragment_target">Target</div>
+ <script>
+ function stashResult(key, results) {
+ fetch(`/css/css-scroll-snap-2/scroll-start-target/stash.py?key=${key}`, {
+ method: "POST",
+ body: JSON.stringify(results)
+ }).then(() => {
+ window.close();
+ });
+ }
+ function record() {
+ let scroll_position = "UNKNOWN";
+ // Expect page is scrolled all the way down as the text is at the bottom of
+ // the page.
+ const expected_scroll_top = document.scrollingElement.scrollHeight -
+ document.scrollingElement.clientHeight;
+
+ const scroll_start_target_top = top_box.getBoundingClientRect().height;
+
+ if (document.scrollingElement.scrollTop == scroll_start_target_top) {
+ scroll_position = "AT_SCROLL_START_TARGET";
+ } else if (document.scrollingElement.scrollTop == expected_scroll_top) {
+ scroll_position = "AT_TEXT_FRAGMENT";
+ }
+
+ const result = {
+ scroll_position: scroll_position
+ };
+
+ let key = (new URL(document.location)).searchParams.get("key");
+ stashResult(key, result);
+ }
+
+ window.onload = () => {
+ window.requestAnimationFrame(function () {
+ window.requestAnimationFrame(record);
+ })
+ }
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation.tentative.html
new file mode 100644
index 0000000000..f83ea1a036
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-text-fragment-navigation.tentative.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target interaction with text-fragment navigation</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script src="/common/utils.js"></script>
+</head>
+
+<body onload="runTest()">
+ <script>
+ function fetchResult(key, resolve, reject) {
+ fetch(`/css/css-scroll-snap-2/scroll-start-target/stash.py?key=${key}`).then(response => {
+ return response.text();
+ }).then(text => {
+ if (text) {
+ try {
+ let result = JSON.parse(text);
+ resolve(result);
+ } catch (e) {
+ reject();
+ }
+ } else {
+ fetchResult(key, resolve, reject);
+ }
+ });
+ }
+
+ function runTest() {
+ promise_test(t => new Promise(async (resolve, reject) => {
+ let key = token();
+
+ test_driver.bless("Open a URL with a text fragment directive", () => {
+ window.open(`scroll-start-target-with-text-fragment-navigation-target.html?key=${key}#:~:text=Target`, "_blank", "noopener");
+ });
+
+ fetchResult(key, resolve, reject);
+ }).then(result => {
+ assert_equals(result.scroll_position, "AT_TEXT_FRAGMENT");
+ }), "scroll-start doesn't override text fragment navigation");
+ }
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-user-programmatic-scroll.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-user-programmatic-scroll.tentative.html
new file mode 100644
index 0000000000..2d487e9b85
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-with-user-programmatic-scroll.tentative.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script src="/dom/events/scrolling/scroll_support.js"></script>
+</head>
+
+<body>
+ <style>
+ .spacer {
+ width: 1000px;
+ height: 1000px;
+ }
+
+ .scroller {
+ width: 300px;
+ height: 300px;
+ border: solid 1px black;
+ overflow: scroll;
+ margin: 0px;
+ position: absolute;
+ }
+
+ .box {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+
+ .top_left {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .center {
+ top: 200px;
+ left: 200px;
+ background-color: purple;
+ scroll-start-target: auto auto;
+ }
+
+ .bottom_right {
+ top: 400px;
+ left: 400px;
+ background-color: yellow;
+ }
+ </style>
+ <div class="scroller" id="user_scroller">
+ <div class="spacer"></div>
+ <div class="top_left box" id="user_top_left_box"></div>
+ <div class="center box"></div>
+ <div class="bottom_right box"></div>
+ </div>
+ <div class="scroller" id="programmatic_scroller" style="left: 500px">
+ <div class="spacer"></div>
+ <div class="top_left box" id="programmatic_top_left_box"></div>
+ <div class="center box"></div>
+ <div class="bottom_right box"></div>
+ </div>
+ <script>
+ async function user_scroll(scroller, current_offset, target_offset) {
+ return new test_driver.Actions().scroll(0, 0,
+ target_offset.x - current_offset.x,
+ target_offset.y - current_offset.y, { origin: scroller })
+ .send();
+ }
+
+ function programmatic_scroll(scroller, current_offset, target_offset) {
+ scroller.scrollTo(target_offset.x, target_offset.y);
+ }
+
+ async function test_scroll_start_target(test, scroller, msg, scrolling_function) {
+ await waitForCompositorCommit();
+ let top_left_box = document.getElementById("user_top_left_box");
+
+ let expected_scroll_top = top_left_box.getBoundingClientRect().height;
+ let expected_scroll_left = top_left_box.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+
+ let scrollend_promise = new Promise((resolve) => {
+ scroller.addEventListener("scrollend", resolve);
+ });
+ const current_offset = { x: scroller.scrollLeft, y: scroller.scrollTop };
+ const target_offset = {
+ x: current_offset.x + 100,
+ y: current_offset.y + 100
+ };
+ await scrolling_function(scroller, current_offset, target_offset);
+
+ // Only wait for scrollend if it is supported.
+ if (window.onscrollend == null || window.onscrollend != undefined) {
+ await scrollend_promise;
+ }
+ assert_approx_equals(scroller.scrollTop, target_offset.y, 1,
+ `${msg} (vertical)`);
+ assert_approx_equals(scroller.scrollLeft, target_offset.x, 1,
+ `${msg} (horizontal)`);
+ }
+
+ promise_test(async (t) => {
+ let scroller = document.getElementById("user_scroller");
+ const msg = "user scroll is not overriden in by scroll-start-target";
+ await test_scroll_start_target(t, scroller, msg, user_scroll);
+ }, "scroll-start-target does not override user scroll");
+
+ promise_test(async (t) => {
+ let scroller = document.getElementById("programmatic_scroller");
+ const msg = "programmatic scroll is not overriden in by scroll-start-target";
+ await test_scroll_start_target(t, scroller, msg, programmatic_scroll);
+ }, "scroll-start-target does not override programmatic scroll");
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target.tentative.html b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target.tentative.html
new file mode 100644
index 0000000000..2e679c3739
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target.tentative.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title> CSS Scroll Snap 2 Test: scroll-start-target*</title>
+ <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <style>
+ .spacer {
+ width: 1000px;
+ height: 1000px;
+ }
+
+ .scroller {
+ width: 300px;
+ height: 300px;
+ border: solid 1px black;
+ overflow: scroll;
+ margin: 0px;
+ position: absolute;
+ }
+
+ .box {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+
+ .top_left {
+ top: 0px;
+ left: 0px;
+ background-color: red;
+ }
+
+ .target_for_x_and_y {
+ scroll-start-target: auto auto;
+ }
+
+ .target_for_x {
+ scroll-start-target: none auto;
+ }
+
+ .center {
+ top: 200px;
+ left: 200px;
+ background-color: purple;
+ }
+
+ .bottom_right {
+ top: 400px;
+ left: 400px;
+ background-color: yellow;
+ }
+ </style>
+ <div class="scroller" id="scroller1">
+ <div class="spacer"></div>
+ <div class="top_left box" id="top_left_box1"></div>
+ <div class="center box target_for_x_and_y" id="centerbox"></div>
+ <div class="bottom_right box"></div>
+ </div>
+ <div class="scroller" id="scroller2">
+ <div class="spacer"></div>
+ <div class="top_left box" id="top_left_box2"></div>
+ <div class="center box target_for_x" id="centerbox2"></div>
+ <div class="bottom_right box"></div>
+ </div>
+ <script>
+ test((t) => {
+ let scroller = document.getElementById("scroller1");
+ let top_left_box = document.getElementById("top_left_box1");
+
+ const expected_scroll_top = top_left_box.getBoundingClientRect().height;
+ const expected_scroll_left = top_left_box.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+ });
+ test((t) => {
+ let scroller = document.getElementById("scroller2");
+ let top_left_box = document.getElementById("top_left_box2");
+
+ const expected_scroll_top = 0;
+ const expected_scroll_left = top_left_box.getBoundingClientRect().width;
+
+ assert_approx_equals(scroller.scrollTop, expected_scroll_top, 1,
+ "scroll-start-target sets initial vertical scroll position");
+ assert_approx_equals(scroller.scrollLeft, expected_scroll_left, 1,
+ "scroll-start-target sets initial horizontal scroll position");
+ });
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/stash.py b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/stash.py
new file mode 100644
index 0000000000..3c65e2b59b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scroll-snap-2/scroll-start-target/stash.py
@@ -0,0 +1,27 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+This file allows the different windows created by
+css/css-scroll-snap-2/scroll-start-target-with-text-fragment-navigation.html
+to store and retrieve data.
+
+scroll-start-target-with-text-fragment-navigation.html (test file) opens a window to
+scroll-start-target-with-text-fragment-navigation-target.html which writes some data
+which the test file will eventually read. This file handles the requests from
+both windows.
+"""
+
+import time
+
+def main(request, response):
+ key = request.GET.first(b"key")
+
+ if request.method == u"POST":
+ # Received result data from target page
+ request.server.stash.put(key, request.body, u'/css/css-scroll-snap-2/scroll-start-target/')
+ return u"ok"
+ else:
+ # Request for result data from test page
+ value = request.server.stash.take(key, u'/css/css-scroll-snap-2/scroll-start-target/')
+ return value