content-visibility-layout-paint-containment-001.html (6268B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>content-visibility and layout/paint 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="content-visibility: auto and elements skipping their content change the used value of the contain property to turn on layout/paint containment, affecting absolute/fixed positioned descendants."> 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 { 23 content-visibility: visible; 24 } 25 #hidden { 26 content-visibility: hidden; 27 } 28 #auto_far { 29 content-visibility: auto; 30 } 31 #auto_close { 32 content-visibility: auto; 33 } 34 #visible_to_hidden { 35 content-visibility: visible; 36 } 37 #hidden_to_visible { 38 content-visibility: hidden; 39 } 40 #visible_to_auto { 41 content-visibility: visible; 42 } 43 #auto_to_visible { 44 content-visibility: auto; 45 } 46 47 /* Selectors for testing absolute/fixed positioning container blocks */ 48 #top_spacer { 49 height: 100px; 50 background: lightgray; 51 } 52 .absolute_pos { 53 position: absolute; 54 top: 42px; 55 } 56 .fixed_pos { 57 position: fixed; 58 top: 42px; 59 } 60 </style> 61 <body> 62 <div id="log"></div> 63 64 <div id="top_spacer"></div> 65 66 <div id="visible" class="content_visibility"> 67 <div class="absolute_pos"></div> 68 <div class="fixed_pos"></div> 69 </div> 70 71 <div id="hidden" class="content_visibility"> 72 <div class="absolute_pos"></div> 73 <div class="fixed_pos"></div> 74 </div> 75 76 <div id="auto_close" class="content_visibility"> 77 <div class="absolute_pos"></div> 78 <div class="fixed_pos"></div> 79 </div> 80 81 <div id="visible_to_hidden" class="content_visibility"> 82 <div class="absolute_pos"></div> 83 <div class="fixed_pos"></div> 84 </div> 85 86 <div id="hidden_to_visible" class="content_visibility"> 87 <div class="absolute_pos"></div> 88 <div class="fixed_pos"></div> 89 </div> 90 91 <div id="visible_to_auto" class="content_visibility"> 92 <div class="absolute_pos"></div> 93 <div class="fixed_pos"></div> 94 </div> 95 96 <div id="auto_to_visible" class="content_visibility"> 97 <div class="absolute_pos"></div> 98 <div class="fixed_pos"></div> 99 </div> 100 101 <div id="spacer_for_far_to_viewport"></div> 102 103 <div id="auto_far" class="content_visibility"> 104 <div class="absolute_pos"></div> 105 <div class="fixed_pos"></div> 106 </div> 107 108 <script> 109 function verifyContainmentFromAbsoluteFixedPositioning(id, applied) { 110 // content-visibility: auto and elements skipping their content change 111 // apply paint/layout containment, making them an absolute/fixed 112 // positioning container blocks. 113 // See contain-paint-dynamic-001.html / contain-layout-dynamic-001.html. 114 115 let container = document.getElementById(id); 116 let containerTop = container.getBoundingClientRect().top; 117 118 let abs_top = container.getElementsByClassName("absolute_pos")[0] 119 .getBoundingClientRect().top; 120 assert_equals(abs_top > containerTop, applied, "absolute positioning containing block"); 121 122 let fixed_top = container.getElementsByClassName("fixed_pos")[0] 123 .getBoundingClientRect().top; 124 assert_equals(fixed_top > containerTop, applied, "fixed positioning containing block"); 125 } 126 127 function setContentVisibility(id, value) { 128 let container = document.getElementById(id); 129 container.style.contentVisibility = value; 130 } 131 132 promise_test(async () => { 133 verifyContainmentFromAbsoluteFixedPositioning("visible", 134 /*applied=*/false); 135 }, "content-visibility: visible"); 136 137 promise_test(async () => { 138 verifyContainmentFromAbsoluteFixedPositioning("hidden", 139 /*applied=*/true); 140 }, "content-visibility: hidden"); 141 142 promise_test(async () => { 143 await waitForAtLeastOneFrame(); 144 verifyContainmentFromAbsoluteFixedPositioning("auto_far", 145 /*applied=*/true); 146 }, "content-visibility: auto (far from viewport)"); 147 148 promise_test(async () => { 149 await waitForAtLeastOneFrame(); 150 verifyContainmentFromAbsoluteFixedPositioning("auto_close", 151 /*applied=*/true); 152 }, "content-visibility: auto (close from viewport)"); 153 154 promise_test(async () => { 155 setContentVisibility("visible_to_hidden", "hidden"); 156 verifyContainmentFromAbsoluteFixedPositioning("visible_to_hidden", 157 /*applied=*/true); 158 }, "switching content-visibility from visible to hidden"); 159 160 promise_test(async () => { 161 setContentVisibility("hidden_to_visible", "visible"); 162 verifyContainmentFromAbsoluteFixedPositioning("hidden_to_visible", 163 /*applied=*/false); 164 }, "switching content-visibility from hidden to visible"); 165 166 promise_test(async () => { 167 setContentVisibility("visible_to_auto", "auto"); 168 await waitForAtLeastOneFrame(); 169 verifyContainmentFromAbsoluteFixedPositioning("visible_to_auto", 170 /*applied=*/true); 171 }, "switching content-visibility from visible to auto"); 172 173 promise_test(async () => { 174 setContentVisibility("auto_to_visible", "visible"); 175 verifyContainmentFromAbsoluteFixedPositioning("auto_to_visible", 176 /*applied=*/false); 177 }, "switching content-visibility from auto to visible"); 178 </script> 179 </body>