target-pseudo-in-has.html (4117B)
1 <!DOCTYPE html> 2 <meta charset="utf-8" /> 3 <title>CSS Selectors Invalidation: :target pseudo-class in :has() argument</title> 4 <link rel="help" href="https://drafts.csswg.org/selectors/#relational"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <style> 8 #parent1 { color: grey; } 9 #parent1:has(:target) { color: green; } 10 11 #parent2 { color: blue; } 12 #parent2:has(:not(:target)) { color: grey; } 13 #parent2:has(:target) { color: green; } 14 15 #parent3 { color: green; } 16 #parent3:not(:has(:target)) { color: grey; } 17 </style> 18 <a href="#fragment">link to #fragment</a> 19 <a href="#fragment2">link to #fragment2</a> 20 <a href="#fragment3">link to #fragment3</a> 21 <a href="#">link to #</a> 22 <div id="parent1"> 23 1: 24 <span id="fragment">Must be green when containing :target</span> 25 </div> 26 <div id="parent2"> 27 2: 28 <span id="fragment2">Must be green when containing :target</span> 29 </div> 30 <div id="parent3"> 31 3: 32 <span id="fragment3">Must be green when containing :target</span> 33 </div> 34 <script> 35 const GREEN = "rgb(0, 128, 0)"; 36 const GREY = "rgb(128, 128, 128)"; 37 const BLUE = "rgb(0, 0, 255)"; 38 39 async function navigateFragment(fragment) { 40 return new Promise(resolve => { 41 let hashChanged = (e) => { 42 if (location.hash.substring(1) === fragment) { 43 resolve(); 44 window.removeEventListener("hashchange", hashChanged); 45 } 46 }; 47 window.addEventListener("hashchange", hashChanged); 48 fragmentLink(fragment).click(); 49 }); 50 } 51 52 function fragmentLink(fragment) { 53 return document.querySelector(`a[href="#${fragment}"]`); 54 } 55 56 promise_test(async () => { 57 const fragment = document.querySelector("#fragment"); 58 const fragment2 = document.querySelector("#fragment2"); 59 const fragment3 = document.querySelector("#fragment3"); 60 61 location.hash = ""; 62 63 assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target"); 64 assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target"); 65 assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target"); 66 67 await navigateFragment("fragment"); 68 69 assert_true(fragment.matches(":target")); 70 assert_equals(getComputedStyle(parent1).color, GREEN, "parent1 should be green on fragment click"); 71 assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target"); 72 assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target"); 73 74 await navigateFragment("fragment2"); 75 76 assert_true(fragment2.matches(":target")); 77 assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target"); 78 assert_equals(getComputedStyle(parent2).color, GREEN, "parent2 should be green on fragment click"); 79 assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target"); 80 81 fragment2.remove(); 82 assert_equals(getComputedStyle(parent2).color, BLUE, "parent2 should be blue after removing only child"); 83 84 parent2.append(fragment2); 85 86 // Skip to check parent2 color since there is nothing in the spec mentioning DOM mutations affecting the target element. 87 // - https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-fragid 88 89 await navigateFragment("fragment3"); 90 91 assert_true(fragment3.matches(":target")); 92 assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target"); 93 assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target"); 94 assert_equals(getComputedStyle(parent3).color, GREEN, "parent3 should be green on fragment click"); 95 96 await navigateFragment(""); 97 98 assert_equals(location.hash, ""); 99 assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target"); 100 assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target"); 101 assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target"); 102 }); 103 </script>