snap-area-overflow-boundary-viewport-covering.tentative.html (5810B)
1 <!DOCTYPE html> 2 <link rel="help" href="https://www.w3.org/TR/css-scroll-snap-1/#snap-overflow" /> 3 <title></title> 4 <meta name="assert" content="Test passes if snap is to the nearest edge"> 5 <style> 6 body { 7 margin: 0px; 8 } 9 #scroller { 10 scroll-snap-type: block mandatory; 11 overflow-y: scroll; 12 height: 400px; 13 width: 400px 14 } 15 #space { 16 width: 200px; 17 height: 4000px; 18 } 19 .box { 20 scroll-snap-align: start; 21 background: #ccccff; 22 margin-bottom: 10px; 23 width: 300px; 24 height: 500px; 25 position: relative; 26 } 27 .header { 28 top: 0; 29 position: absolute; 30 } 31 .footer { 32 bottom: 0; 33 position: absolute; 34 } 35 </style> 36 <script src="/resources/testharness.js"></script> 37 <script src="/resources/testharnessreport.js"></script> 38 <script src="/resources/testdriver.js"></script> 39 <script src="/resources/testdriver-vendor.js"></script> 40 <script src="/resources/testdriver-actions.js"></script> 41 <script src="/dom/events/scrolling/scroll_support.js"></script> 42 <script src="../support/common.js"></script> 43 44 <div id="scroller" tabindex="0"> 45 <div id="target" class="box"> 46 <div class="header">Header 1</div> 47 <div class="footer">Footer 1</div> 48 </div> 49 <div id="next" class="box"> 50 <div class="header">Header 2</div> 51 <div class="footer">Footer 2</div> 52 </div> 53 <div id="space"></div> 54 </div> 55 56 <script> 57 // If all of the following conditions are met: 58 // 1. the snap area is larger than the snapport along the scroll axis, and 59 // 2. the distance between the previous and subsequent snap positions along 60 // the axis is greater then the snapport size. 61 // 62 // Then any scroll position in which the snap area covers the snapport is 63 // valid snap position. This rule facilitates scrolling around in oversized 64 // elements. 65 // 66 // These test covers edge cases with snap-areas that overflow the snapport. 67 // It should be possible to scroll to the end of an oversized snap-area. 68 69 const scroller = document.getElementById("scroller"); 70 const target = document.getElementById("target"); 71 const next = document.getElementById("next"); 72 const scrollTop = () => { 73 return scroller.scrollTop; 74 }; 75 const cleanup = () => { 76 target.style.height = '500px'; 77 }; 78 79 promise_test(async t => { 80 await waitForCompositorCommit(); 81 t.add_cleanup(cleanup); 82 scroller.scrollTo(0, 0); 83 assert_equals(scroller.scrollTop, 0, "verify test pre-condition"); 84 85 // Ensure we can freely scroll in an oversized element. 86 let scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller); 87 await keyPress(scroller, "ArrowDown"); 88 await scrollEndPromise; 89 assert_greater_than(scroller.scrollTop, 0, 90 'Arrowkey scroll moved scroll position'); 91 assert_less_than_equal(scroller.scrollTop, target.clientHeight, 92 'Scroll within snap-area overflow'); 93 94 // Resize the element so it is oversized by less than the line scroll amount. 95 // The next keyboard-triggered scroll should stop at the end of the snap-area. 96 // Otherwise it is not possible to scroll to the last line of the snap-area 97 // via keyboard. 98 const scrollAmount = scroller.scrollTop; 99 target.style.height = `${scroller.clientHeight + 2 * scrollAmount - 1}px`; 100 assert_equals(scroller.scrollTop, scrollAmount, "Verify container remains " + 101 "at the same covering snap offset."); 102 scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller); 103 await keyPress(scroller, "ArrowDown"); 104 await scrollEndPromise; 105 assert_equals(scroller.scrollTop, 106 target.clientHeight - scroller.clientHeight, 107 'End boundary of snap-area is valid snap target'); 108 109 // Must not get stuck at a snap position. Since already at the end of the 110 // snap area, we should advance to the next. 111 scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller); 112 await keyPress(scroller, "ArrowDown"); 113 await scrollEndPromise; 114 assert_equals(scroller.scrollTop, 115 next.offsetTop, 116 'Advance to next snap-area'); 117 118 }, "Keyboard scrolling with vertical snap-area overflow"); 119 120 promise_test(async t => { 121 await waitForScrollReset(t, scroller); 122 await waitForCompositorCommit(); 123 assert_equals(scroller.scrollTop, 0, "verify test pre-condition"); 124 125 // Ensure we can freely scroll in an oversized element. 126 let scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller); 127 await new test_driver.Actions() 128 .scroll(50, 50, 0, 50, {origin: scroller}) 129 .send(); 130 await scrollEndPromise; 131 assert_equals(scroller.scrollTop, 50, 132 'Wheel-scroll moved scroll position'); 133 134 // Target position for wheel scroll overshoots the boundary of the snap-area. 135 // Ensure that we stop at the boundary. 136 let scrollAmount = 137 target.clientHeight - scroller.clientHeight - scroller.scrollTop + 1; 138 139 scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller); 140 await new test_driver.Actions() 141 .scroll(50, 50, 0, scrollAmount, {origin: scroller}) 142 .send(); 143 await scrollEndPromise; 144 assert_equals(scroller.scrollTop, 100, 145 'End boundary of snap-area is valid snap target'); 146 147 // Must not get stuck at a snap position. Since already at the end of the 148 // snap area, we should advance to the next. scrollAmount must be enough to 149 // advance to next snap position. 150 scrollAmount = next.clientHeight / 2 + 10 /* margin-bottom */; 151 scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller); 152 await new test_driver.Actions() 153 .scroll(50, 50, 0, scrollAmount, {origin: scroller}) 154 .send(); 155 await scrollEndPromise; 156 assert_equals(scroller.scrollTop, next.offsetTop, 157 'Advance to next snap-area'); 158 159 }, "Mouse-wheel scrolling with vertical snap-area overflow"); 160 </script>