anchor-scope-basic.html (8544B)
1 <!DOCTYPE html> 2 <title>CSS Anchor Positioning: Basic anchor-scope behavior</title> 3 <link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#anchor-scope"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <style> 7 .scope-all { anchor-scope: all; } 8 .scope-a { anchor-scope: --a; } 9 .scope-b { anchor-scope: --b; } 10 .scope-ab { anchor-scope: --a, --b; } 11 12 .anchor-a { anchor-name: --a; } 13 .anchor-b { anchor-name: --b; } 14 .anchor-ab { anchor-name: --a, --b; } 15 .anchor-a, .anchor-b, .anchor-ab { 16 background: skyblue; 17 height: 10px; 18 } 19 20 .anchored-a { position-anchor: --a; } 21 .anchored-b { position-anchor: --b; } 22 .anchored-a, .anchored-b { 23 position: absolute; 24 top: anchor(bottom); 25 left: anchor(left); 26 width: 5px; 27 height: 5px; 28 background: coral; 29 } 30 31 /* Containing block */ 32 main { 33 position: relative; 34 width: 100px; 35 height: 100px; 36 border: 1px solid black; 37 } 38 </style> 39 <script> 40 function inflate(t, template_element) { 41 t.add_cleanup(() => main.replaceChildren()); 42 main.append(template_element.content.cloneNode(true)); 43 } 44 </script> 45 46 <main id=main> 47 </main> 48 49 <template id=test_inclusive_subtree> 50 <div class="scope-a anchor-a"> <!--A--> 51 <div class=anchored-a></div> 52 </div> 53 </template> 54 <script> 55 test((t) => { 56 inflate(t, test_inclusive_subtree); 57 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '10px'); 58 }, 'Can anchor to a name both defined and scoped by the same element'); 59 </script> 60 61 <template id=test_skips_named_anchor_with_scope> 62 <div class="anchor-a"></div> 63 <div class="anchor-a"></div> 64 <div class="anchor-a"></div> <!--A--> 65 <div class="scope-a anchor-a"></div> 66 <div class=anchored-a></div> 67 </template> 68 <script> 69 test((t) => { 70 inflate(t, test_skips_named_anchor_with_scope); 71 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '30px'); 72 }, 'Sibling can not anchor into anchor-scope, even when anchor-name present'); 73 </script> 74 75 <template id=test_scope_all_common_ancestor> 76 <div class=scope-all> 77 <div class=anchor-a></div> 78 <div class=anchor-a></div> 79 <div class=anchor-a></div> 80 <div class=anchor-a></div><!--A--> 81 <div class=anchored-a></div> 82 </div> 83 </template> 84 <script> 85 test((t) => { 86 inflate(t, test_scope_all_common_ancestor); 87 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '40px'); 88 }, 'anchor-scope:all on common ancestor'); 89 </script> 90 91 <template id=test_scope_named_common_ancestor> 92 <div class=scope-a> 93 <div class=anchor-a></div> 94 <div class=anchor-a></div> 95 <div class=anchor-a></div> 96 <div class=anchor-a></div><!--A--> 97 <div class=anchored-a></div> 98 </div> 99 </template> 100 <script> 101 test((t) => { 102 inflate(t, test_scope_named_common_ancestor); 103 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '40px'); 104 }, 'anchor-scope:--a on common ancestor'); 105 </script> 106 107 <template id=test_scope_all_sibling> 108 <div class=anchor-a></div> 109 <div class=anchor-a></div><!--A--> 110 <div class=scope-all> 111 <div class=anchor-a></div> 112 <div class=anchor-a></div> 113 </div> 114 <div class=anchored-a></div> 115 </template> 116 <script> 117 test((t) => { 118 inflate(t, test_scope_all_sibling); 119 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '20px'); 120 }, 'anchor-scope:all on sibling'); 121 </script> 122 123 <template id=test_scope_all_multiple> 124 <div class=anchor-b></div><!--B--> 125 <div class=anchor-a></div><!--A--> 126 <div class=scope-all> 127 <div class=anchor-b></div> 128 <div class=anchor-a></div> 129 </div> 130 <div class=anchored-a></div> 131 <div class=anchored-b></div> 132 </template> 133 <script> 134 test((t) => { 135 inflate(t, test_scope_all_multiple); 136 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '20px'); 137 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '10px'); 138 }, 'anchor-scope:all scopes multiple names'); 139 </script> 140 141 <template id=test_scope_ab> 142 <div class=anchor-b></div><!--B--> 143 <div class=anchor-a></div><!--A--> 144 <div class=scope-ab> 145 <div class=anchor-b></div> 146 <div class=anchor-a></div> 147 </div> 148 <div class=anchored-a></div> 149 <div class=anchored-b></div> 150 </template> 151 <script> 152 test((t) => { 153 inflate(t, test_scope_ab); 154 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '20px'); 155 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '10px'); 156 }, 'anchor-scope:--a,--b scopes --a and --b'); 157 </script> 158 159 <template id=test_scope_a> 160 <div class=anchor-b></div> 161 <div class=anchor-a></div><!--A--> 162 <div class=scope-a> 163 <div class=anchor-b></div> 164 <div class=anchor-ab></div><!--B--> 165 <div class=anchor-a></div> 166 </div> 167 <div class=anchored-a></div> 168 <div class=anchored-b></div> 169 </template> 170 <script> 171 test((t) => { 172 inflate(t, test_scope_a); 173 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '20px'); 174 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '40px'); 175 }, 'anchor-scope:--a scopes only --a'); 176 </script> 177 178 <template id=test_scope_b> 179 <div class=anchor-b></div><!--B--> 180 <div class=anchor-a></div> 181 <div class=scope-b> 182 <div class=anchor-a></div><!--A--> 183 <div class=anchor-b></div> 184 </div> 185 <div class=anchored-a></div> 186 <div class=anchored-b></div> 187 </template> 188 <script> 189 test((t) => { 190 inflate(t, test_scope_b); 191 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '30px'); 192 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '10px'); 193 }, 'anchor-scope:--b scopes only --b'); 194 </script> 195 196 <template id=test_out_of_flow_anchors> 197 <style> 198 .anchor-a, .anchor-b { 199 position: absolute; 200 width: 5px; 201 height: 5px; 202 } 203 </style> 204 <div class=anchor-b style='left:10px'></div> 205 <div class=anchor-a style='left:20px'></div><!--A--> 206 <div class=scope-a> 207 <div class=anchor-b style='left:30px'></div><!--B--> 208 <div class=anchor-a style='left:40px'></div> 209 </div> 210 <div class=anchored-a></div> 211 <div class=anchored-b></div> 212 </template> 213 <script> 214 test((t) => { 215 inflate(t, test_out_of_flow_anchors); 216 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '5px'); 217 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).left, '20px'); 218 219 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '5px'); 220 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).left, '30px'); 221 }, 'anchor-scope:--a scopes only --a (out-of-flow anchors)'); 222 </script> 223 224 <!-- Out-of-flow anchor within anchor-scope:--a --> 225 <template id=test_mixed_flow_anchors> 226 <style> 227 .abs { 228 position: absolute; 229 width: 5px; 230 height: 5px; 231 } 232 </style> 233 <div class=anchor-b></div> 234 <div class=anchor-a></div><!--A--> 235 <div class=scope-a> 236 <div class=anchor-b></div><!--B--> 237 <div class='anchor-a abs' style='top:50px'></div> 238 </div> 239 <div class=anchored-a></div> 240 <div class=anchored-b></div> 241 </template> 242 <script> 243 test((t) => { 244 inflate(t, test_mixed_flow_anchors); 245 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '20px'); 246 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).left, '0px'); 247 248 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '30px'); 249 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).left, '0px'); 250 }, 'anchor-scope:--a scopes only --a (both out-of-flow and in-flow anchors)'); 251 </script> 252 253 <!-- In-flow anchor within anchor-scope:--a --> 254 <template id=test_mixed_flow_anchors_reverse> 255 <style> 256 .abs { 257 position: absolute; 258 width: 5px; 259 height: 5px; 260 } 261 </style> 262 <div class=anchor-b></div> 263 <div class='anchor-a abs' style='top:50px'></div><!--A--> 264 <div class=scope-a> 265 <div class=anchor-b></div><!--B--> 266 <div class=anchor-a></div> 267 </div> 268 <div class=anchored-a></div> 269 <div class=anchored-b></div> 270 </template> 271 <script> 272 test((t) => { 273 inflate(t, test_mixed_flow_anchors_reverse); 274 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).top, '55px'); 275 assert_equals(getComputedStyle(main.querySelector('.anchored-a')).left, '0px'); 276 277 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).top, '20px'); 278 assert_equals(getComputedStyle(main.querySelector('.anchored-b')).left, '0px'); 279 }, 'anchor-scope:--a scopes only --a (both out-of-flow and in-flow anchors, reverse)'); 280 </script>