attribute-or-elemental-selectors-in-has.html (5556B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>CSS Selectors Invalidation: :has() invalidation basic</title> 4 <link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <link rel="help" href="https://drafts.csswg.org/selectors/#relational"> 8 <style> 9 div, main { color: grey } 10 .subject:has(> .child) { color: red } 11 .subject:has(.descendant) { color: green } 12 .subject:has([attrname=descendant]) { color: blue } 13 .subject:has(#div_descendant) { color: yellow } 14 .subject:has(descendant) { color: yellowgreen } 15 </style> 16 <main id=main> 17 <div id=div_subject class="subject"> 18 <div id=div_child> 19 <div id=div_grandchild></div> 20 </div> 21 </div> 22 </main> 23 <script> 24 let grey = 'rgb(128, 128, 128)'; 25 let red = 'rgb(255, 0, 0)'; 26 let green = 'rgb(0, 128, 0)'; 27 let blue = 'rgb(0, 0, 255)'; 28 let yellow = 'rgb(255, 255, 0)'; 29 let yellowgreen = 'rgb(154, 205, 50)'; 30 31 function test_div(test_name, el, color) { 32 test(function() { 33 assert_equals(getComputedStyle(el).color, color); 34 }, test_name + ': div#' + el.id + '.color'); 35 } 36 37 test_div('initial_color', div_subject, grey); 38 test_div('initial_color', div_child, grey); 39 test_div('initial_color', div_grandchild, grey); 40 41 div_child.classList.add('child'); 42 test_div('add .child to #div_child', div_subject, red); 43 div_child.classList.remove('child'); 44 test_div('remove .child from #div_child', div_subject, grey); 45 46 div_grandchild.classList.add('child'); 47 test_div('add .child to #div_grandchild', div_subject, grey); 48 div_grandchild.classList.remove('child'); 49 test_div('remove .child from #div_grandchild', div_subject, grey); 50 51 div_child.classList.add('descendant'); 52 test_div('add .descendant to #div_child', div_subject, green); 53 div_child.classList.remove('descendant'); 54 test_div('remove .descendant from #div_child', div_subject, grey); 55 56 div_grandchild.classList.add('descendant'); 57 test_div('add .descendant to #div_grandchild', div_subject, green); 58 div_grandchild.classList.remove('descendant'); 59 test_div('remove .descendant from #div_grandchild', div_subject, grey); 60 61 div_grandchild.setAttribute('attrname', 'descendant'); 62 test_div('set descendant to #div_grandchild[attrname]', div_subject, blue); 63 div_grandchild.setAttribute('attrname', ''); 64 test_div('clear #div_grandchild[attrname]', div_subject, grey); 65 66 div_grandchild.id = 'div_descendant'; 67 test_div('change #div_grandchild to #div_descendant', div_subject, yellow); 68 div_descendant.id = 'div_grandchild'; 69 test_div('change #div_descendant to #div_grandchild', div_subject, grey); 70 71 { 72 const descendant = document.createElement('descendant'); 73 div_subject.appendChild(descendant); 74 test_div('add descendant to #div_subject', div_subject, yellowgreen); 75 div_subject.removeChild(descendant); 76 test_div('remove descendant from #div_subject', div_subject, grey); 77 } 78 79 { 80 const div = document.createElement('div'); 81 const descendant = document.createElement('descendant'); 82 div.appendChild(descendant); 83 div_subject.appendChild(div); 84 test_div('add "div > descendant" to #div_subject', div_subject, yellowgreen); 85 div_subject.removeChild(div); 86 test_div('remove "div > descendant" from #div_subject', div_subject, grey); 87 } 88 89 { 90 const child = document.createElement('div'); 91 child.classList.add('child'); 92 div_subject.appendChild(child); 93 test_div('add div.child to #div_subject', div_subject, red); 94 div_subject.removeChild(child); 95 test_div('remove div.child from #div_subject', div_subject, grey); 96 } 97 98 { 99 const descendant = document.createElement('div'); 100 descendant.classList.add('descendant'); 101 const div = document.createElement('div'); 102 div.appendChild(descendant); 103 div_subject.appendChild(div); 104 test_div('add "div > div.descendant" to #div_subject', div_subject, green); 105 div_subject.removeChild(div); 106 test_div('remove "div > div.descendant" from #div_subject', div_subject, grey); 107 } 108 109 { 110 const child = document.createElement('div'); 111 child.id = 'div_descendant'; 112 div_subject.appendChild(child); 113 test_div('add div#div_descendant to #div_subject', div_subject, yellow); 114 div_subject.removeChild(child); 115 test_div('remove div#div_descendant from #div_subject', div_subject, grey); 116 } 117 118 { 119 const descendant = document.createElement('div'); 120 descendant.id = 'div_descendant'; 121 const div = document.createElement('div'); 122 div.appendChild(descendant); 123 div_subject.appendChild(div); 124 test_div('add "div#div_descendant" to #div_subject', div_subject, yellow); 125 div_subject.removeChild(div); 126 test_div('remove "div#div_descendant" from #div_subject', div_subject, grey); 127 } 128 129 { 130 const child = document.createElement('div'); 131 child.setAttribute('attrname', 'descendant'); 132 div_subject.appendChild(child); 133 test_div('add div[attrname] to #div_subject', div_subject, blue); 134 div_subject.removeChild(child); 135 test_div('remove div[attrname] from #div_subject', div_subject, grey); 136 } 137 138 { 139 const descendant = document.createElement('div'); 140 descendant.setAttribute('attrname', 'descendant'); 141 const div = document.createElement('div'); 142 div.appendChild(descendant); 143 div_subject.appendChild(div); 144 test_div('add "div > div[attrname]" to #div_subject', div_subject, blue); 145 div_subject.removeChild(div); 146 test_div('remove "div > div[attrname]" from #div_subject', div_subject, grey); 147 } 148 149 </script>