scrollsnapchange-after-layout-change.tentative.html (6024B)
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#snap-events" /> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/dom/events/scrolling/scroll_support.js"></script> 9 <script src="/css/css-scroll-snap/snap-events/resources/common.js"></script> 10 <script src="/web-animations/testcommon.js"></script> 11 </head> 12 13 <body> 14 <style> 15 #scroller { 16 overflow: scroll; 17 scroll-snap-type: y mandatory; 18 height: 200px; 19 width: 200px; 20 border: solid 1px; 21 position: absolute; 22 } 23 24 .snap_area { 25 position: absolute; 26 width: 100px; 27 left: calc(50% - 50px); 28 } 29 30 #outer_snap_area { 31 scroll-snap-align: start none; 32 height: 1000px; 33 background-color: blue; 34 } 35 36 #inner_snap_area { 37 scroll-snap-align: start none; 38 height: 100px; 39 top: 100px; 40 background-color: yellow; 41 } 42 </style> 43 <div id="scroller"> 44 <div id="outer_snap_area" class="snap_area"></div> 45 <div id="inner_snap_area" class="snap_area"></div> 46 </div> 47 <script> 48 let scroller = document.getElementById("scroller"); 49 50 async function reset(t) { 51 inner_snap_area.style.height = "100px"; 52 inner_snap_area.style.scrollSnapAlign = "start none"; 53 outer_snap_area.style.scrollSnapAlign = "start none"; 54 scroller.style.scrollSnapType = "y mandatory"; 55 await resetTargetScrollState(t, scroller); 56 } 57 58 async function setup(t) { 59 checkSnapEventSupport("scrollsnapchange"); 60 await reset(t); 61 await waitForCompositorCommit(); 62 assert_equals(scroller.scrollTop, 0, "test precondition: scroller " + 63 "is not scrolled."); 64 } 65 66 promise_test(async (t) => { 67 await setup(t); 68 let target_snap_position = inner_snap_area.offsetTop + 69 inner_snap_area.offsetHeight; 70 // Scroll to an offset close to the bottom of the inner snap area and 71 // expect to snap to an offset just below this snap area. 72 let scrollend_promise = waitForScrollendEventNoTimeout(scroller); 73 scroller.scrollTo(0, target_snap_position - 10); 74 await scrollend_promise; 75 assert_equals(scroller.scrollTop, target_snap_position, 76 "scroller snaps to just below the inner snap area."); 77 // We are just below the inner snap area. Increase its height so that it 78 // is larger than the snapport and straddled by the snapport. Verify 79 // that we snap to its bottom. 80 let scrollsnapchange_promise = waitForScrollSnapChangeEvent(scroller); 81 inner_snap_area.style.height = 82 `${scroller.clientHeight + inner_snap_area.clientHeight - 10}px`; 83 const evt = await scrollsnapchange_promise; 84 assertSnapEvent(evt, { block: inner_snap_area, inline: null }); 85 target_snap_position = inner_snap_area.offsetTop + 86 inner_snap_area.offsetHeight - scroller.clientHeight; 87 assert_equals(scroller.scrollTop, target_snap_position, 88 "scroller snaps to the bottom of the smaller snap area (which is " + 89 "now covering)."); 90 }, "scrollsnapchange fires after snap area is snapped to upon layout change."); 91 92 promise_test(async (t) => { 93 await setup(t); 94 let target_snap_position = inner_snap_area.offsetTop + 95 inner_snap_area.offsetHeight; 96 // Scroll to an offset close to the bottom of the inner snap area and 97 // expect to snap to an offset just below this snap area. 98 let scrollend_promise = waitForScrollendEventNoTimeout(scroller); 99 scroller.scrollTo(0, target_snap_position - 10); 100 await scrollend_promise; 101 assert_equals(scroller.scrollTop, target_snap_position, 102 "scroller snaps to just below the inner snap area."); 103 // We are just below the inner snap area. Increase its height so that it 104 // is larger than the snapport making the current scroll position 105 // a valid covering position within the inner snap area. 106 let scrollsnapchange_promise = waitForScrollSnapChangeEvent(scroller, false); 107 inner_snap_area.style.height = 108 `${scroller.clientHeight + inner_snap_area.clientHeight + 10}px`; 109 const evt = await scrollsnapchange_promise; 110 assertSnapEvent(evt, { block: inner_snap_area, inline: null }); 111 assert_equals(scroller.scrollTop, target_snap_position, 112 "scroller maintains offset which is now covering within inner area"); 113 }, "scrollsnapchange fires after snap area is snapped to upon layout change " + 114 "without scroll."); 115 116 promise_test(async(t) => { 117 await setup(t); 118 await waitForCompositorCommit(); 119 let scrollsnapchange_promise = waitForScrollSnapChangeEvent(scroller, false); 120 scroller.style.scrollSnapType = "none"; 121 let evt = await scrollsnapchange_promise; 122 assertSnapEvent(evt, { block: null, inline: null }); 123 scrollsnapchange_promise = waitForScrollSnapChangeEvent(scroller, false); 124 scroller.style.scrollSnapType = "y mandatory"; 125 evt = await scrollsnapchange_promise; 126 assertSnapEvent(evt, { block: outer_snap_area, inline: null }); 127 }, "scrollsnapchange fires when container stops snapping"); 128 129 promise_test(async(t) => { 130 await setup(t); 131 await waitForCompositorCommit(); 132 let scrollsnapchange_promise = waitForScrollSnapChangeEvent(scroller, false); 133 inner_snap_area.style.scrollSnapAlign = "none"; 134 outer_snap_area.style.scrollSnapAlign = "none"; 135 let evt = await scrollsnapchange_promise; 136 assertSnapEvent(evt, { block: null, inline: null }); 137 scrollsnapchange_promise = waitForScrollSnapChangeEvent(scroller, false); 138 inner_snap_area.style.scrollSnapAlign = "start"; 139 outer_snap_area.style.scrollSnapAlign = "start"; 140 evt = await scrollsnapchange_promise; 141 assertSnapEvent(evt, { block: outer_snap_area, inline: null }); 142 }, "scrollsnapchange fires when snap container no longer has snap areas"); 143 </script> 144 </body> 145 </html>