contain-paint-dynamic-001.html (6085B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Dynamic change to paint containment</title> 4 <link rel="help" href="https://drafts.csswg.org/css-contain/#contain-property"> 5 <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1765615"> 6 <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <meta name="assert" content="Verify paint containment is properly updated after dynamic change to the contain property."> 10 <style> 11 /* Selectors for contain */ 12 #none .wrapper { 13 contain: none; 14 } 15 #paint .wrapper { 16 contain: paint; 17 } 18 #none_to_paint .wrapper { 19 contain: none; 20 } 21 #paint_to_none .wrapper { 22 contain: paint; 23 } 24 25 /* Selectors for testing absolute/fixed positioned elements */ 26 #top_spacer { 27 height: 100px; 28 background: lightgray; 29 } 30 .absolute_pos { 31 position: absolute; 32 top: 42px; 33 } 34 .fixed_pos { 35 position: fixed; 36 top: 42px; 37 } 38 39 /* Selectors for testing IFC (floats) */ 40 .floatleft { 41 float: left; 42 } 43 .clearleft { 44 clear: left; 45 } 46 47 /* Selectors for testing IFC (margin collapsing) */ 48 .blockmargin { 49 margin: 25px 0; 50 } 51 .wrapper.blockmargin { 52 background: lightgray; 53 } 54 55 .rect { 56 background: black; 57 width: 50px; 58 height: 100px; 59 } 60 </style> 61 <body> 62 <div id="log"></div> 63 64 <div id="top_spacer"></div> 65 66 <div id="none"> 67 <div class="wrapper"> 68 <div class="absolute_pos"></div> 69 <div class="fixed_pos"></div> 70 </div> 71 <div> 72 <div class="floatleft rect"></div> 73 <div class="wrapper"> 74 <div class="clearleft rect"></div> 75 </div> 76 </div> 77 <div> 78 <div class="wrapper blockmargin"> 79 <div class="rect blockmargin"></div> 80 </div> 81 </div> 82 </div> 83 84 <div id="paint"> 85 <div class="wrapper"> 86 <div class="absolute_pos"></div> 87 <div class="fixed_pos"></div> 88 </div> 89 <div> 90 <div class="floatleft rect"></div> 91 <div class="wrapper"> 92 <div class="clearleft rect"></div> 93 </div> 94 </div> 95 <div> 96 <div class="wrapper blockmargin"> 97 <div class="rect blockmargin"></div> 98 </div> 99 </div> 100 </div> 101 102 <div id="none_to_paint"> 103 <div class="wrapper"> 104 <div class="absolute_pos"></div> 105 <div class="fixed_pos"></div> 106 </div> 107 <div> 108 <div class="floatleft rect"></div> 109 <div class="wrapper"> 110 <div class="clearleft rect"></div> 111 </div> 112 </div> 113 <div> 114 <div class="wrapper blockmargin"> 115 <div class="rect blockmargin"></div> 116 </div> 117 </div> 118 </div> 119 120 <div id="paint_to_none"> 121 <div class="wrapper"> 122 <div class="absolute_pos"></div> 123 <div class="fixed_pos"></div> 124 </div> 125 <div> 126 <div class="floatleft rect"></div> 127 <div class="wrapper"> 128 <div class="clearleft rect"></div> 129 </div> 130 </div> 131 <div> 132 <div class="wrapper blockmargin"> 133 <div class="rect blockmargin"></div> 134 </div> 135 </div> 136 </div> 137 138 <script> 139 function verifyPaintContainment(id, applied) { 140 let container = document.getElementById(id); 141 let wrappers = container.getElementsByClassName("wrapper"); 142 143 // To verify the containment box establishes an absolute positioning 144 // containing block and a fixed positioning containing block, we test 145 // positions of absolutely/fixed positioned children (a bit below the 146 // containment box rather than a bit below the top of the viewport). 147 let containingBlockTop = wrappers[0].getBoundingClientRect().top; 148 let absTop = container.getElementsByClassName("absolute_pos")[0] 149 .getBoundingClientRect().top; 150 assert_equals(absTop > containingBlockTop, applied, "absolute positioning containing block"); 151 let fixedTop = container.getElementsByClassName("fixed_pos")[0] 152 .getBoundingClientRect().top; 153 assert_equals(fixedTop > containingBlockTop, applied, "fixed positioning containing block"); 154 155 // To verify the containment box establishes an independent formatting 156 // context, we test position the clear: left div with respect to the 157 // float: left div. 158 let floatLeft = wrappers[1].previousElementSibling; 159 let clearLeft = wrappers[1].firstElementChild; 160 let clearNextToFloat = Math.abs(floatLeft.getBoundingClientRect().top - clearLeft.getBoundingClientRect().top) <= 1; 161 assert_equals(clearNextToFloat, applied, "independent formatting context"); 162 163 // In addition, we verify that the margin inside the containment box 164 // are not collapsed. 165 let IFCWithMargin = wrappers[2]; 166 let childWithMargin = IFCWithMargin.firstElementChild; 167 let marginCollapsed = Math.abs(IFCWithMargin.getBoundingClientRect().height - childWithMargin.getBoundingClientRect().height) <= 1; 168 assert_equals(!marginCollapsed, applied, "independent formatting context (margins collapsing)"); 169 } 170 171 function setContain(id, value) { 172 let container = document.getElementById(id); 173 Array.from(container.getElementsByClassName("wrapper")) 174 .forEach(element => element.style.contain = value); 175 } 176 177 promise_test(async () => { 178 await document.fonts.ready; 179 verifyPaintContainment("none", /* applied=*/false); 180 }, "contain: none"); 181 182 promise_test(async () => { 183 await document.fonts.ready; 184 verifyPaintContainment("paint", /* applied=*/true); 185 }, "contain: paint"); 186 187 promise_test(async () => { 188 await document.fonts.ready; 189 setContain("none_to_paint", "paint"); 190 verifyPaintContainment("none_to_paint", /* applied=*/true) 191 }, "switching contain from none to paint"); 192 193 promise_test(async () => { 194 await document.fonts.ready; 195 setContain("paint_to_none", "none"); 196 verifyPaintContainment("paint_to_none", /* applied=*/false); 197 }, "switching contain from paint to none"); 198 </script> 199 </body>