| <!DOCTYPE html> | |
| <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-type" /> | |
| <meta name="viewport" content="user-scalable=no"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <style> | |
| div { | |
| position: absolute; | |
| } | |
| :root { | |
| overflow: scroll; | |
| scroll-snap-type: both mandatory; | |
| } | |
| .scroller { | |
| overflow: scroll; | |
| scroll-snap-type: both mandatory; | |
| padding: 0px; | |
| } | |
| #outer { | |
| left: 1000px; | |
| top: 1000px; | |
| width: 600px; | |
| height: 600px; | |
| } | |
| #out-snap-1 { | |
| scroll-snap-align: start; | |
| left: 1200px; | |
| top: 1200px; | |
| width: 10px; | |
| height: 10px; | |
| } | |
| #out-snap-2 { | |
| scroll-snap-align: start; | |
| left: 1100px; | |
| top: 1100px; | |
| width: 10px; | |
| height: 10px; | |
| } | |
| #inner { | |
| left: 1000px; | |
| top: 1000px; | |
| width: 400px; | |
| height: 400px; | |
| } | |
| .space { | |
| left: 0px; | |
| top: 0px; | |
| width: 3000px; | |
| height: 3000px; | |
| } | |
| #target { | |
| scroll-snap-align: end; | |
| left: 800px; | |
| top: 800px; | |
| width: 200px; | |
| height: 200px; | |
| } | |
| </style> | |
| <div class="space"></div> | |
| <div id="out-snap-1"></div> | |
| <div id="out-snap-2"></div> | |
| <div class="scroller" id="outer"> | |
| <div class="space"></div> | |
| <div class="scroller" id="inner"> | |
| <div class="space"></div> | |
| <div id="target"></div> | |
| </div> | |
| </div> | |
| <script> | |
| var outer = document.getElementById("outer"); | |
| var inner = document.getElementById("inner"); | |
| var target = document.getElementById("target"); | |
| test(() => { | |
| // Initial layout triggers a scroll snap. Reset position before calling | |
| // scrollIntoView. | |
| window.scrollTo(0, 0); | |
| outer.scrollTo(0, 0); | |
| inner.scrollTo(0, 0); | |
| target.scrollIntoView({inline: "start", block: "start"}); | |
| // Although the scrollIntoView specified "start" as the alignment, the target | |
| // has "end" as its snap-alignment. So the inner scroller finishes with "end" | |
| // alignment | |
| assert_equals(inner.scrollLeft, 1000 - inner.clientWidth, "ScrollIntoView lands on the target's snap position regardless of the specified alignment."); | |
| assert_equals(inner.scrollTop, 1000 - inner.clientHeight, "ScrollIntoView lands on the target's snap position regardless of the specified alignment."); | |
| // Since there is no snap points defined in the outer scroller, the outer | |
| // scroller finishes with "start" alignment, as specified in scrollIntoView. | |
| // Note that the "start" alignment aligns the target's top-left corner | |
| //(inner.left + inner.clientWidth - target.width, inner.top + inner.clientHeight - target.height) | |
| // with the outer scroller's top-left corner. | |
| assert_equals(outer.scrollLeft, 800 + inner.clientWidth, "ScrollIntoView ends with the specified alignment if no snap position is specified."); | |
| assert_equals(outer.scrollTop, 800 + inner.clientHeight, "ScrollIntoView ends with the specified alignment if no snap position is specified."); | |
| // Although the scrollIntoView specified "start" as the alignment, the window | |
| // has two other elements with snap points. So the window finishes with the | |
| // closest snap point. | |
| assert_equals(window.scrollX, 1100, "ScrollIntoView lands on the snap position closest to the specified alignment."); | |
| assert_equals(window.scrollY, 1100, "ScrollIntoView lands on the snap position closest to the specified alignment."); | |
| }, "All the scrollers affected by scrollIntoView should land on a snap position if one exists. Otherwise, land according to the specified alignment"); | |
| </script> |