view-timeline-dynamic.html (5701B)
1 <!DOCTYPE html> 2 <title>Changes to view-timeline are reflected in dependent elements</title> 3 <link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-timeline-shorthand"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/web-animations/testcommon.js"></script> 7 <script src="support/testcommon.js"></script> 8 <style> 9 @keyframes anim { 10 from { z-index: 0; } 11 to { z-index: 100; } 12 } 13 .scroller { 14 overflow: hidden; 15 width: 100px; 16 height: 100px; 17 } 18 .scroller > div { 19 height: 100px; 20 } 21 #target { 22 height: 0px; 23 z-index: -1; 24 } 25 </style> 26 <main id=main></main> 27 <script> 28 setup(assert_implements_animation_timeline); 29 30 function inflate(t, template) { 31 t.add_cleanup(() => main.replaceChildren()); 32 main.append(template.content.cloneNode(true)); 33 main.offsetTop; 34 } 35 async function scrollTop(e, value) { 36 e.scrollTop = value; 37 await waitForNextFrame(); 38 } 39 async function scrollLeft(e, value) { 40 e.scrollLeft = value; 41 await waitForNextFrame(); 42 } 43 </script> 44 45 <template id=dynamic_view_timeline_attachment> 46 <style> 47 #scroller { 48 timeline-scope: --t1; 49 } 50 .timeline { 51 view-timeline: --t1; 52 } 53 #target { 54 animation: anim 1s linear; 55 animation-timeline: --t1; 56 } 57 </style> 58 <div id=scroller class=scroller> 59 <div id=div75></div> 60 <div id=div25></div> 61 <div id=div_before></div> 62 <div id=target></div> 63 </div> 64 </template> 65 <script> 66 promise_test(async (t) => { 67 inflate(t, dynamic_view_timeline_attachment); 68 69 await scrollTop(scroller, 50); 70 71 // scrollTop=50 is 75% for div75. 72 div75.classList.add('timeline'); 73 await waitForCSSScrollTimelineStyle(); 74 assert_equals(getComputedStyle(target).zIndex, '75', 'div75'); 75 76 // Identical timelines in div75 and div25 creates an ambiguity. 77 div25.classList.add('timeline'); 78 await waitForCSSScrollTimelineStyle(); 79 assert_equals(getComputedStyle(target).zIndex, '-1', 'ambiguous'); 80 // Removing the timeline from div75 unambiguously links div25 to the 81 // timeline, making scrollTop=50 at 25% for div25. 82 div75.classList.remove('timeline'); 83 await waitForCSSScrollTimelineStyle(); 84 assert_equals(getComputedStyle(target).zIndex, '25', 'div25'); 85 86 // scrollTop=50 is before the timeline start for div_before. 87 div25.classList.remove('timeline'); 88 div_before.classList.add('timeline'); 89 await waitForCSSScrollTimelineStyle(); 90 assert_equals(getComputedStyle(target).zIndex, '-1', 'ahead of div_before'); 91 // Scroll to 25% (for div_before) to verify that we're linked to that 92 // timeline. 93 await scrollTop(scroller, 150); 94 assert_equals(getComputedStyle(target).zIndex, '25', 'div_before'); 95 96 // Linking the timeline back to div25 verifies that the new scrollTop=150 is 97 // actually at 75%. 98 div_before.classList.remove('timeline'); 99 div25.classList.add('timeline'); 100 await waitForCSSScrollTimelineStyle(); 101 assert_equals(getComputedStyle(target).zIndex, '75', 'div25 again'); 102 }, 'Dynamically changing view-timeline attachment'); 103 </script> 104 105 <template id=dynamic_view_timeline_axis> 106 <style> 107 #timeline { 108 view-timeline: --t1; 109 width: 100px; 110 height: 100px; 111 margin: 100px; 112 } 113 #target { 114 animation: anim 1s linear; 115 animation-timeline: --t1; 116 } 117 </style> 118 <div id=scroller class=scroller> 119 <div id=timeline style="background: red;"> 120 <div id=target></div> 121 </div> 122 </div> 123 </template> 124 <script> 125 promise_test(async (t) => { 126 inflate(t, dynamic_view_timeline_axis); 127 128 await scrollTop(scroller, 50); // 25% (vertical) 129 await scrollLeft(scroller, 20); // 10% (horizontal) 130 131 assert_equals(getComputedStyle(target).zIndex, '25', 'vertical'); 132 timeline.style.viewTimelineAxis = 'x'; 133 await waitForCSSScrollTimelineStyle(); 134 assert_equals(getComputedStyle(target).zIndex, '10', 'horizontal'); 135 }, 'Dynamically changing view-timeline-axis'); 136 </script> 137 138 <template id=dynamic_view_timeline_inset> 139 <style> 140 #timeline { 141 width: 100px; 142 height: 100px; 143 margin: 100px; 144 view-timeline: --t1; 145 } 146 #target { 147 animation: anim 1s linear; 148 animation-timeline: --t1; 149 } 150 </style> 151 <div id=scroller class=scroller> 152 <div id=timeline style="background: red;"> 153 <div id=target></div> 154 </div> 155 </div> 156 </template> 157 <script> 158 promise_test(async (t) => { 159 inflate(t, dynamic_view_timeline_inset); 160 161 await scrollTop(scroller, 50); // 25% (without inset). 162 163 assert_equals(getComputedStyle(target).zIndex, '25', 'without inset'); 164 timeline.style.viewTimelineInset = '0px 50px'; 165 await waitForCSSScrollTimelineStyle(); 166 assert_equals(getComputedStyle(target).zIndex, '0', 'with inset'); 167 }, 'Dynamically changing view-timeline-inset'); 168 </script> 169 170 <template id=timeline_display_none> 171 <style> 172 #scroller { 173 timeline-scope: --t1; 174 } 175 #timeline { 176 view-timeline: --t1; 177 } 178 #target { 179 animation: anim 1s linear; 180 animation-timeline: --t1; 181 } 182 </style> 183 <div id=scroller class=scroller> 184 <div></div> 185 <div id=timeline></div> 186 <div id=target></div> 187 </div> 188 </template> 189 <script> 190 promise_test(async (t) => { 191 inflate(t, timeline_display_none); 192 193 await scrollTop(scroller, 50); 194 assert_equals(getComputedStyle(target).zIndex, '25', 'display:block'); 195 timeline.style.display = 'none'; 196 await waitForNextFrame(); 197 // The timeline became inactive. 198 assert_equals(getComputedStyle(target).zIndex, '-1', 'display:none'); 199 }, 'Element with scoped view-timeline becoming display:none'); 200 </script>