nested-declarations-matching.html (6100B)
1 <!DOCTYPE html> 2 <title>CSS Nesting: CSSNestedDeclarations matching</title> 3 <link rel="help" href="https://drafts.csswg.org/css-nesting-1/#nested-declarations-rule"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 7 <style> 8 .trailing { 9 --x: FAIL; 10 & { --x: FAIL; } 11 --x: PASS; 12 } 13 </style> 14 <div class=trailing></div> 15 <script> 16 test(() => { 17 let e = document.querySelector('.trailing'); 18 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 19 }, 'Trailing declarations apply after any preceding rules'); 20 </script> 21 22 23 <style> 24 .trailing_no_leading { 25 & { --x: FAIL; } 26 --x: PASS; 27 } 28 </style> 29 <div class=trailing_no_leading></div> 30 <script> 31 test(() => { 32 let e = document.querySelector('.trailing_no_leading'); 33 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 34 }, 'Trailing declarations apply after any preceding rules (no leading)'); 35 </script> 36 37 38 <style> 39 .trailing_multiple { 40 --x: FAIL; 41 --y: FAIL; 42 --z: FAIL; 43 --w: FAIL; 44 & { --x: FAIL; } 45 --x: PASS; 46 --y: PASS; 47 & { --z: FAIL; } 48 --z: PASS; 49 --w: PASS; 50 } 51 </style> 52 <div class=trailing_multiple></div> 53 <script> 54 test(() => { 55 let e = document.querySelector('.trailing_multiple'); 56 let s = getComputedStyle(e); 57 assert_equals(s.getPropertyValue('--x'), 'PASS'); 58 assert_equals(s.getPropertyValue('--y'), 'PASS'); 59 assert_equals(s.getPropertyValue('--z'), 'PASS'); 60 assert_equals(s.getPropertyValue('--w'), 'PASS'); 61 }, 'Trailing declarations apply after any preceding rules (multiple)'); 62 </script> 63 64 65 <style> 66 .trailing_specificity { 67 --x: FAIL; 68 :is(&, div.nomatch2) { --x: PASS; } /* Specificity: (0, 1, 1) */ 69 --x: FAIL; /* Specificity: (0, 1, 0) */ 70 } 71 </style> 72 <div class=trailing_specificity></div> 73 <script> 74 test(() => { 75 let e = document.querySelector('.trailing_specificity'); 76 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 77 }, 'Nested declarations rule has same specificity as outer selector'); 78 </script> 79 80 81 <style> 82 #nomatch, .specificity_top_level { 83 --x: FAIL; 84 :is(&, div.nomatch2) { --x: PASS; } /* Specificity: (0, 1, 1) */ 85 --x: FAIL; /* Specificity: (0, 1, 0). In particular, this does not have 86 specificity like :is(#nomatch, .specificity_top_level). */ 87 } 88 </style> 89 <div class=specificity_top_level></div> 90 <script> 91 test(() => { 92 let e = document.querySelector('.specificity_top_level'); 93 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 94 }, 'Nested declarations rule has top-level specificity behavior'); 95 </script> 96 97 98 <style> 99 #nomatch, .specificity_top_level_max, div.specificity_top_level_max { 100 --x: FAIL; 101 :is(:where(&), div.nomatch2) { --x: FAIL; } /* Specificity: (0, 1, 1) */ 102 --x: PASS; /* Specificity: (0, 1, 1) (for div.specificity_top_level_max) */ 103 } 104 </style> 105 <div class=specificity_top_level_max></div> 106 <script> 107 test(() => { 108 let e = document.querySelector('.specificity_top_level_max'); 109 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 110 }, 'Nested declarations rule has top-level specificity behavior (max matching)'); 111 </script> 112 113 <style> 114 .nested_pseudo::after { 115 --x: FAIL; 116 @media (width > 0px) { 117 --x: PASS; 118 } 119 } 120 </style> 121 <div class=nested_pseudo></div> 122 <script> 123 test(() => { 124 let e = document.querySelector('.nested_pseudo'); 125 assert_equals(getComputedStyle(e, '::after').getPropertyValue('--x'), 'PASS'); 126 }, 'Bare declartaion in nested grouping rule can match pseudo-element'); 127 </script> 128 129 <style> 130 #nomatch, .nested_group_rule { 131 --x: FAIL; 132 @media (width > 0px) { 133 --x: FAIL; /* Specificity: (0, 1, 0) */ 134 } 135 --x: PASS; 136 } 137 </style> 138 <div class=nested_group_rule></div> 139 <script> 140 test(() => { 141 let e = document.querySelector('.nested_group_rule'); 142 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 143 }, 'Nested group rules have top-level specificity behavior'); 144 </script> 145 146 147 <style> 148 .nested_scope_rule { 149 div:where(&) { /* Specificity: (0, 0, 1) */ 150 --x: PASS; 151 } 152 @scope (&) { 153 --x: FAIL; /* Specificity: (0, 0, 0) */ 154 } 155 } 156 </style> 157 <div class=nested_scope_rule></div> 158 <script> 159 test(() => { 160 let e = document.querySelector('.nested_scope_rule'); 161 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 162 }, 'Nested @scope rules behave like :where(:scope)'); 163 </script> 164 165 166 <style> 167 .nested_scope_rule_trailing { 168 div:where(&) { /* Specificity: (0, 0, 1) */ 169 --x: PASS; 170 } 171 @scope (&) { 172 --ignored: 1; 173 .ignored {} 174 --x: FAIL; /* Specificity: (0, 0, 0) */ 175 } 176 } 177 </style> 178 <div class=nested_scope_rule_trailing></div> 179 <script> 180 test(() => { 181 let e = document.querySelector('.nested_scope_rule_trailing'); 182 assert_equals(getComputedStyle(e).getPropertyValue('--x'), 'PASS'); 183 }, 'Nested @scope rules behave like :where(:scope) (trailing)'); 184 </script> 185 186 187 <style id=set_parent_selector_text_style> 188 .set_parent_selector_text { 189 div { 190 color: red; 191 } 192 .a1 { 193 .ignored {} 194 color: green; 195 } 196 } 197 </style> 198 <div class=set_parent_selector_text> 199 <div class=a1>A1</div> 200 <div class=a2>A2</div> 201 </div> 202 <script> 203 test(() => { 204 let a1 = document.querySelector('.set_parent_selector_text > .a1'); 205 let a2 = document.querySelector('.set_parent_selector_text > .a2'); 206 assert_equals(getComputedStyle(a1).color, 'rgb(0, 128, 0)'); 207 assert_equals(getComputedStyle(a2).color, 'rgb(255, 0, 0)'); 208 209 let rules = set_parent_selector_text_style.sheet.cssRules; 210 assert_equals(rules.length, 1); 211 assert_equals(rules[0].cssRules.length, 2); 212 213 let a_rule = rules[0].cssRules[1]; 214 assert_equals(a_rule.selectorText, '& .a1'); 215 a_rule.selectorText = '.a2'; 216 assert_equals(a_rule.selectorText, '& .a2'); 217 218 assert_equals(getComputedStyle(a1).color, 'rgb(255, 0, 0)'); 219 assert_equals(getComputedStyle(a2).color, 'rgb(0, 128, 0)'); 220 }, 'Nested declarations rule responds to parent selector text change'); 221 </script>