targeted-scroll-marker-selection.tentative.html (8000B)
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <title>CSS Test: scroll tracking for ::scroll-markers whose orignatin elements cannot be scroll-aligned </title> 7 <link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll"> 8 <script src="/resources/testharness.js"></script> 9 <script src="/resources/testharnessreport.js"></script> 10 <script src="/resources/testdriver.js"></script> 11 <script src="/resources/testdriver-actions.js"></script> 12 <script src="/resources/testdriver-vendor.js"></script> 13 <script src="/css/css-transitions/support/helper.js"></script> 14 <script src="/dom/events/scrolling/scroll_support.js"></script> 15 <script src="support/scroll-marker-support.js"></script> 16 </head> 17 18 <body> 19 <style> 20 .wrapper { 21 display: grid; 22 justify-content: center; 23 } 24 25 .carousel { 26 display: grid; 27 grid-auto-flow: column; 28 width: 1600px; 29 height: 512px; 30 overflow-x: scroll; 31 scroll-snap-type: x mandatory; 32 list-style-type: none; 33 scroll-behavior: smooth; 34 border: solid 2px grey; 35 padding-top: 10%; 36 text-align: center; 37 counter-set: markeridx -1; 38 39 div>.item { 40 &>.itemchild { 41 42 } 43 scroll-snap-align: center; 44 height: 80%; 45 width: 318px; 46 border: 1px solid; 47 place-content: center; 48 49 &::scroll-marker { 50 content: counter(markeridx); 51 counter-increment: markeridx; 52 align-content: center; 53 text-align: center; 54 width: 35px; 55 height: 35px; 56 border: 3px solid gray; 57 border-radius: 50%; 58 margin: 3px; 59 background-color: red; 60 } 61 62 &::scroll-marker:target-current { 63 background-color: green; 64 } 65 &::scroll-marker:checked { 66 background-color: green; 67 } 68 } 69 70 scroll-marker-group: after; 71 72 &::scroll-marker-group { 73 height: 45px; 74 display: flex; 75 align-items: center; 76 justify-content: center; 77 border: solid 1px black; 78 border-radius: 30px; 79 } 80 } 81 </style> 82 <div class="wrapper" id="wrapper"> 83 <div class="carousel" id="carousel"> 84 <div> 85 <div class="item" id="item0" tabindex=0> 86 <div class="itemchild" id="itemchild0">0</div> 87 </div> 88 <div class="itemsibling" id="itemsibling0"></div> 89 </div> 90 <div> 91 <div class="item" id="item1" tabindex=0> 92 <div class="itemchild" id="itemchild1">1</div> 93 </div> 94 <div class="itemsibling" id="itemsibling1"></div> 95 </div> 96 <div> 97 <div class="item" id="item2" tabindex=0> 98 <div class="itemchild" id="itemchild2">2</div> 99 </div> 100 <div class="itemsibling" id="itemsibling2"></div> 101 </div> 102 <div> 103 <div class="item" id="item3" tabindex=0> 104 <div class="itemchild" id="itemchild3">3</div> 105 </div> 106 <div class="itemsibling" id="itemsibling3"></div> 107 </div> 108 <div> 109 <div class="item" id="item4" tabindex=0> 110 <div class="itemchild" id="itemchild4">4</div> 111 </div> 112 <div class="itemsibling" id="itemsibling4"></div> 113 </div> 114 <div> 115 <div class="item" id="item5" tabindex=0> 116 <div class="itemchild" id="itemchild5">5</div> 117 </div> 118 <div class="itemsibling" id="itemsibling5"></div> 119 </div> 120 <div> 121 <div class="item" id="item6" tabindex=0> 122 <div class="itemchild" id="itemchild6">6</div> 123 </div> 124 <div class="itemsibling" id="itemsibling6"></div> 125 </div> 126 <div> 127 <div class="item" id="item7" tabindex=0> 128 <div class="itemchild" id="itemchild7">7</div> 129 </div> 130 <div class="itemsibling" id="itemsibling7"></div> 131 </div> 132 <div> 133 <div class="item" id="item8" tabindex=0> 134 <div class="itemchild" id="itemchild8">8</div> 135 </div> 136 <div class="itemsibling" id="itemsibling8"></div> 137 </div> 138 <div> 139 <div class="item" id="item9" tabindex=0> 140 <div class="itemchild" id="itemchild9">9</div> 141 </div> 142 <div class="itemsibling" id="itemsibling9"></div> 143 </div> 144 <div> 145 <div class="item" id="item10" tabindex=0> 146 <div class="itemchild" id="itemchild10">10</div> 147 </div> 148 <div class="itemsibling" id="itemsibling10"></div> 149 </div> 150 <div> 151 <div class="item" id="item11" tabindex=0> 152 <div class="itemchild" id="itemchild11">11</div> 153 </div> 154 <div class="itemsibling" id="itemsibling11"></div> 155 </div> 156 <div> 157 <div class="item" id="item12" tabindex=0> 158 <div class="itemchild" id="itemchild12">12</div> 159 </div> 160 <div class="itemsibling" id="itemsibling12"></div> 161 </div> 162 <div> 163 <div class="item" id="item13" tabindex=0> 164 <div class="itemchild" id="itemchild13">13</div> 165 </div> 166 <div class="itemsibling" id="itemsibling13"></div> 167 </div> 168 <div> 169 <div class="item" id="item14" tabindex=0> 170 <div class="itemchild" id="itemchild14">14</div> 171 </div> 172 <div class="itemsibling" id="itemsibling14"></div> 173 </div> 174 <div> 175 <div class="item" id="item15" tabindex=0> 176 <div class="itemchild" id="itemchild15">15</div> 177 </div> 178 <div class="itemsibling" id="itemsibling15"></div> 179 </div> 180 </div> 181 </div> 182 <script> 183 184 const carousel = document.getElementById("carousel"); 185 const items = document.querySelectorAll(".item"); 186 const wrapper = document.getElementById("wrapper"); 187 188 RED = "rgb(255, 0, 0)"; 189 GREEN = "rgb(0, 128, 0)"; 190 191 const max_scroll_offset = carousel.scrollWidth - carousel.clientWidth; 192 async function testTargetedHasActiveMarker(test, element, expected_idx) { 193 // Start from somewhere in the middle, ensuring that scrolling to the 194 // extremes generates scrollend events. 195 await waitForScrollReset(test, carousel, max_scroll_offset / 2); 196 const color = 197 getComputedStyle(items[expected_idx], "::scroll-marker").backgroundColor; 198 assert_not_equals(color, GREEN, 199 `Target item ${expected_idx} is not selected yet.`); 200 const scrollend_promise = waitForScrollendEventNoTimeout(carousel); 201 element.scrollIntoView({behavior: "smooth"}); 202 await scrollend_promise; 203 verifySelectedMarker(expected_idx, items, GREEN, RED); 204 } 205 206 promise_test(async(t) => { 207 // Item 1 cannot be snap-aligned because there is not enough 208 // room for its scroll container to be aligned to its center. 209 const target_item = items[1]; 210 await testTargetedHasActiveMarker(t, target_item, 1); 211 }, "scroll-marker of target (idx 1) of scrollIntoView is selected"); 212 213 promise_test(async(t) => { 214 // Item 14 cannot be snap-aligned because there is not enough 215 // room for its scroll container to be aligned to its center. 216 const target_item = items[14]; 217 await testTargetedHasActiveMarker(t, target_item, 14); 218 }, "scroll-marker of target (idx 14) of scrollIntoView is selected"); 219 220 promise_test(async(t) => { 221 const item14 = items[14]; 222 const target_item = item14.querySelector(".itemchild"); 223 // Item 14 is the parent. We call scrollIntoView on its child. 224 await testTargetedHasActiveMarker(t, target_item, 14); 225 }, "scroll-marker of parent of target of scrollIntoView is selected"); 226 227 promise_test(async(t) => { 228 const item14 = items[14]; 229 const target_item = item14.nextElementSibling; 230 // Item 14 is before itemsibling14 in the DOM. We call scrollIntoView on 231 // itemsibling14. 232 await testTargetedHasActiveMarker(t, target_item, 14); 233 }, "scroll-marker of earlier sibling of target of scrollIntoView is selected"); 234 </script> 235 </body> 236 237 </html>