content-visibility-size-containment-001.html (9683B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>content-visibility and size containment</title> 4 <link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> 5 <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1765615"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/common/rendering-utils.js"></script> 9 <meta name="assert" content="elements skipping their content change the used value of the contain property to turn on size containment."> 10 <style> 11 /* Selectors for content-visibility */ 12 #spacer_for_far_to_viewport { 13 height: 300vh; 14 } 15 .content_visibility { 16 /* Dynamic modification of content-visibility may change whether style 17 containment is applied, which in turn may cause drastic invalidations 18 (e.g. rebuilding counters). Make the test more robust by forcing 19 style containment to always apply. */ 20 contain: style; 21 } 22 #visible .content_visibility { 23 content-visibility: visible; 24 } 25 #hidden .content_visibility { 26 content-visibility: hidden; 27 } 28 #auto_far .content_visibility { 29 content-visibility: auto; 30 } 31 #auto_close .content_visibility { 32 content-visibility: auto; 33 } 34 #visible_to_hidden .content_visibility { 35 content-visibility: visible; 36 } 37 #hidden_to_visible .content_visibility { 38 content-visibility: hidden; 39 } 40 #visible_to_auto_far .content_visibility { 41 content-visibility: visible; 42 } 43 #auto_far_to_visible .content_visibility { 44 content-visibility: auto; 45 } 46 #hidden_to_auto_close .content_visibility { 47 content-visibility: hidden; 48 } 49 #auto_close_to_hidden .content_visibility { 50 content-visibility: auto; 51 } 52 #auto_dynamic_relevancy .content_visibility { 53 content-visibility: auto; 54 } 55 56 /* Selectors for testing sizing as empty */ 57 .content_visibility { 58 display: inline-block; 59 } 60 .box { 61 display: inline-block; 62 width: 50px; 63 height: 5px; 64 background: black; 65 } 66 </style> 67 <body> 68 <div id="log"></div> 69 70 <div id="visible"> 71 <div class="content_visibility"><div class="box"></div></div> 72 </div> 73 74 <div id="hidden"> 75 <div class="content_visibility"><div class="box"></div></div> 76 </div> 77 78 <div id="auto_close"> 79 <div class="content_visibility"><div class="box"></div></div> 80 </div> 81 82 <div id="visible_to_hidden"> 83 <div class="content_visibility"><div class="box"></div></div> 84 </div> 85 86 <div id="hidden_to_visible"> 87 <div class="content_visibility"><div class="box"></div></div> 88 </div> 89 90 <div id="hidden_to_auto"> 91 <div class="content_visibility"><div class="box"></div></div> 92 </div> 93 94 <div id="auto_to_hidden"> 95 <div class="content_visibility"><div class="box"></div></div> 96 </div> 97 98 <div id="hidden_to_auto_close"> 99 <div class="content_visibility"><div class="box"></div></div> 100 </div> 101 102 <div id="auto_close_to_hidden"> 103 <div class="content_visibility"><div class="box"></div></div> 104 </div> 105 106 <div id="spacer_for_far_to_viewport"></div> 107 108 <div id="auto_far"> 109 <div class="content_visibility"><div class="box"></div></div> 110 </div> 111 112 <div id="visible_to_auto_far"> 113 <div class="content_visibility"><div class="box"></div></div> 114 </div> 115 116 <div id="auto_far_to_visible"> 117 <div class="content_visibility"><div class="box"></div></div> 118 </div> 119 120 121 <div id="auto_dynamic_relevancy"> 122 <div tabindex="1"></div> 123 <div class="content_visibility" tabindex="2"><div class="box"></div></div> 124 </div> 125 126 <script> 127 function sizeContainmentApplied(id) { 128 // To verify size containment, we test the width is zero. 129 // See contain-size-dynamic-001.html for more details. 130 let container = document.getElementById(id); 131 let content_visibility = container.getElementsByClassName("content_visibility")[0]; 132 return content_visibility.getBoundingClientRect().width == 0; 133 } 134 135 function setContentVisibility(id, value) { 136 let container = document.getElementById(id); 137 let content_visibility = container.getElementsByClassName("content_visibility")[0]; 138 content_visibility.style.contentVisibility = value; 139 } 140 141 promise_test(async () => { 142 assert_false(sizeContainmentApplied("visible")); 143 }, "content-visibility: visible"); 144 145 promise_test(async () => { 146 assert_true(sizeContainmentApplied("hidden")); 147 }, "content-visibility: hidden"); 148 149 promise_test(async () => { 150 await waitForAtLeastOneFrame(); 151 assert_true(sizeContainmentApplied("auto_far")); 152 }, "content-visibility: auto (far from viewport)"); 153 154 promise_test(async () => { 155 await waitForAtLeastOneFrame(); 156 assert_false(sizeContainmentApplied("auto_close")); 157 }, "content-visibility: auto (close from viewport)"); 158 159 promise_test(async () => { 160 setContentVisibility("visible_to_hidden", "hidden"); 161 assert_true(sizeContainmentApplied("visible_to_hidden")); 162 }, "switching content-visibility from visible to hidden"); 163 164 promise_test(async () => { 165 setContentVisibility("hidden_to_visible", "visible"); 166 assert_false(sizeContainmentApplied("hidden_to_visible")); 167 }, "switching content-visibility from hidden to visible"); 168 169 promise_test(async () => { 170 setContentVisibility("auto_far_to_visible", "visible"); 171 assert_false(sizeContainmentApplied("auto_far_to_visible")); 172 }, "switching content-visibility from auto (far from viewport) to visible"); 173 174 promise_test(async () => { 175 setContentVisibility("visible_to_auto_far", "auto"); 176 await waitForAtLeastOneFrame(); 177 assert_true(sizeContainmentApplied("visible_to_auto_far")); 178 }, "switching content-visibility from visible to auto (far from viewport)"); 179 180 promise_test(async () => { 181 setContentVisibility("auto_close_to_hidden", "hidden"); 182 assert_true(sizeContainmentApplied("auto_close_to_hidden")); 183 }, "switching content-visibility from auto (close from viewport) to hidden"); 184 185 promise_test(async () => { 186 setContentVisibility("hidden_to_auto_close", "auto"); 187 await waitForAtLeastOneFrame(); 188 assert_false(sizeContainmentApplied("hidden_to_auto_close")); 189 }, "switching content-visibility from hidden to auto (close from viewport)"); 190 191 192 let contentVisibilityAuto = 193 document.getElementById("auto_dynamic_relevancy"). 194 getElementsByClassName("content_visibility")[0]; 195 196 function clearRelevancyReasons() { 197 // Scrolling auto_dynamic_relevancy far from the viewport, unfocus it 198 // and unselect it. Also temporarily set its content-visibility to 199 // 'hidden' before scrolling to give more chance for browsers to 200 // re-apply size containment, especially if they fail the corresponding 201 // tests "going back to initial state" below. 202 setContentVisibility("auto_dynamic_relevancy", "hidden"); 203 window.scrollTo(0, 0); 204 document.getElementById("auto_dynamic_relevancy") 205 .firstElementChild.focus({preventScroll: true}); 206 window.getSelection().empty(); 207 setContentVisibility("auto_dynamic_relevancy", "auto"); 208 } 209 210 promise_test(async (t) => { 211 t.add_cleanup(clearRelevancyReasons); 212 213 await waitForAtLeastOneFrame(); 214 assert_true(sizeContainmentApplied("auto_dynamic_relevancy"), 215 "size containment applied when initially far to the viewport"); 216 217 contentVisibilityAuto.scrollIntoView(); 218 await waitForAtLeastOneFrame(); 219 assert_false(sizeContainmentApplied("auto_dynamic_relevancy"), 220 "size containment applied when changing from far to close to the viewport"); 221 222 window.scrollTo(0, 0); 223 assert_true(sizeContainmentApplied("auto_dynamic_relevancy"), 224 "size containment applied when changing back from close to far to the viewport"); 225 }, "content-visibility: auto, changing proximity to the viewport"); 226 227 promise_test(async (t) => { 228 t.add_cleanup(clearRelevancyReasons); 229 230 await waitForAtLeastOneFrame(); 231 assert_true(sizeContainmentApplied("auto_dynamic_relevancy"), 232 "size containment applied when initially unfocused"); 233 234 contentVisibilityAuto.focus({preventScroll: true}); 235 await waitForAtLeastOneFrame(); 236 assert_false(sizeContainmentApplied("auto_dynamic_relevancy"), 237 "size containment applied after focusing"); 238 239 document.getElementById("auto_dynamic_relevancy") 240 .firstElementChild.focus({preventScroll: true}); 241 assert_true(sizeContainmentApplied("auto_dynamic_relevancy"), 242 "size containment applied after unfocusing back"); 243 }, "content-visibility: auto, after being focused/unfocused"); 244 245 promise_test(async (t) => { 246 t.add_cleanup(clearRelevancyReasons); 247 248 await waitForAtLeastOneFrame(); 249 assert_true(sizeContainmentApplied("auto_dynamic_relevancy"), 250 "size containment applied when initially unselected"); 251 252 window.getSelection().selectAllChildren(contentVisibilityAuto); 253 await waitForAtLeastOneFrame(); 254 assert_false(sizeContainmentApplied("auto_dynamic_relevancy"), 255 "size containment applied when after selecting"); 256 257 window.getSelection().empty(); 258 await waitForAtLeastOneFrame(); 259 assert_true(sizeContainmentApplied("auto_dynamic_relevancy"), 260 "size containment applied when unselecting back"); 261 }, "content-visibility: auto, after being selected/unselected"); 262 263 </script> 264 </body>