scope-proximity.html (3852B)
1 <!DOCTYPE html> 2 <title>@scope - proximity to root</title> 3 <link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scope-proximity"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script> 7 8 function test_scope(script_element, callback_fn, description) { 9 test((t) => { 10 // The provided <script> element must be an immedate subsequent sibling of 11 // a <template> element. 12 let template_element = script_element.previousElementSibling; 13 assert_equals(template_element.tagName, 'TEMPLATE'); 14 15 t.add_cleanup(() => { 16 while (main.firstChild) 17 main.firstChild.remove() 18 }); 19 20 main.append(template_element.content.cloneNode(true)); 21 22 callback_fn(); 23 }, description); 24 } 25 26 function assert_green(selector) { 27 assert_equals(getComputedStyle(main.querySelector(selector)).backgroundColor, 'rgb(0, 128, 0)'); 28 } 29 function assert_not_green(selector) { 30 assert_equals(getComputedStyle(main.querySelector(selector)).backgroundColor, 'rgb(0, 0, 0)'); 31 } 32 </script> 33 <style> 34 main * { 35 background-color: black; 36 } 37 </style> 38 <main id=main> 39 </main> 40 41 <template> 42 <style> 43 .item { 44 padding: 0px; 45 border: 5px solid red; 46 } 47 48 @scope (.light) { 49 [id] { border-color: rgb(100, 100, 100); } 50 } 51 52 @scope (.dark) { 53 [id] { border-color: rgb(200, 200, 200); } 54 } 55 </style> 56 <div class=light> 57 <div id=item1> 58 <div class=dark> 59 <div id=item2> 60 <div class=light> 61 <div id=item3> 62 <div class=dark> 63 <div id=item4></div> 64 </div> 65 </div> 66 </div> 67 </div> 68 </div> 69 </div> 70 </div> 71 </template> 72 <script> 73 test_scope(document.currentScript, () => { 74 assert_equals(getComputedStyle(item1).borderColor, 'rgb(100, 100, 100)'); 75 assert_equals(getComputedStyle(item2).borderColor, 'rgb(200, 200, 200)'); 76 assert_equals(getComputedStyle(item3).borderColor, 'rgb(100, 100, 100)'); 77 assert_equals(getComputedStyle(item4).borderColor, 'rgb(200, 200, 200)'); 78 }, 'Alternating light/dark'); 79 </script> 80 81 82 <template> 83 <style> 84 @scope (.b) { 85 [id] { border-color:green; } 86 } 87 @scope (.a) { 88 [id] { border-color:red; } 89 } 90 </style> 91 <div class=a> 92 <div class=b> 93 <span id=item></span> 94 </div> 95 </div> 96 </template> 97 <script> 98 test_scope(document.currentScript, () => { 99 assert_equals(getComputedStyle(item).borderColor, 'rgb(0, 128, 0)'); 100 }, 'Proximity wins over order of appearance'); 101 </script> 102 103 104 <template> 105 <style> 106 @scope (.a) { 107 span[id] { border-color:green; } 108 } 109 @scope (.b) { 110 [id] { border-color:red; } 111 } 112 </style> 113 <div class=a> 114 <div class=b> 115 <span id=item></span> 116 </div> 117 </div> 118 </template> 119 <script> 120 test_scope(document.currentScript, () => { 121 assert_equals(getComputedStyle(item).borderColor, 'rgb(0, 128, 0)'); 122 }, 'Specificity wins over proximity'); 123 </script> 124 125 <template> 126 <style> 127 @scope (.foo) { 128 .bar span[id] { border-color:green; } 129 } 130 </style> 131 <div class=foo> 132 <div class="foo bar"> 133 <span id=item></span> 134 </div> 135 </div> 136 </template> 137 <script> 138 test_scope(document.currentScript, () => { 139 assert_equals(getComputedStyle(item).borderColor, 'rgb(0, 128, 0)'); 140 }, 'Identical root with further proximity is not ignored'); 141 </script> 142 143 <template> 144 <style> 145 @scope (.scope) { 146 :where(&) { border-color:green; } 147 } 148 @scope (#outer) { 149 :where(:scope) :where(#inner) { border-color:red; } 150 } 151 </style> 152 <div id=outer class=scope> 153 <div> 154 <div id=inner class=scope> 155 </div> 156 </div> 157 </div> 158 </template> 159 <script> 160 test_scope(document.currentScript, () => { 161 assert_equals(getComputedStyle(inner).borderColor, 'rgb(0, 128, 0)'); 162 }, 'Most proximate match wins under multiple scoping roots'); 163 </script>