Status: FAIL | Duration: 55ms | Subtests: 0/11 | Open test on wpt.live | wpt.fyi
Data from commit:
a50cb89 wpt: run reference-named files which are themselves tests (#836) (2026-09-03)
| Subtest | Status | Message |
|---|---|---|
| @scope (#main) { .b { } } and .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) to (.b) { .a { } } and .a | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main, .foo, .bar) { #a { } } and #a | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { div.b { } } and div.b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { :scope .b { } } and .a .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { & .b { } } and :where(#main) .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { div .b { } } and div .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { @scope (.a) { .b { } } } and .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { :scope .b { } } and :scope .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope { & .b { } } and :where(:scope) .b | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
| @scope (#main) { > .a { } } and :where(#main) > .a | FAIL | assert_equals: scoped rule expected "1" but got "auto" |
/css/css-cascade/scope-specificity.html
<!DOCTYPE html> <title>@scope - specificity</title> <link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scope-atrule"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <style id=style> </style> <main id=main> <style id=styleImplicit></style> <div id=a class=a> <div id=b class=b> </div> </div> </main> <script> // Format a scoped style rule using the selector at scoped_selector's last element, // with each preceding array item representing an enclosing @scope rule. // // Example: // // scoped_selector=['@scope (foo)', '@scope (bar)', 'div'] // declarations='z-index:42' // => '@scope (foo) { @scope (bar) { div { z-index:42 } } }' function format_scoped_rule(scoped_selector, declarations) { if (scoped_selector.length < 2) { throw "Fail"; } let scope_prelude = scoped_selector[0]; let remainder = scoped_selector.slice(1); let content = remainder.length == 1 ? `${remainder[0]} { ${declarations} }` : format_scoped_rule(remainder, declarations); return `${scope_prelude} { ${content} }`; } // Verify that the specificity of 'scoped_selector' is the same // as the specificity of 'ref_selector'. Both selectors must select // an element within #main. function test_scope_specificity(scoped_selector, ref_selector, style) { if (style === undefined) { style = document.getElementById("style"); } test(t => { t.add_cleanup(() => { style.textContent = ''; }); let element = main.querySelector(ref_selector); assert_not_equals(element, null); let scoped_rule = format_scoped_rule(scoped_selector, 'z-index:1'); let ref_rule = `:is(${ref_selector}) { z-index:2 }`; style.textContent = `${scoped_rule}`; assert_equals(getComputedStyle(element).zIndex, '1', 'scoped rule'); style.textContent = `${ref_rule}`; assert_equals(getComputedStyle(element).zIndex, '2', 'unscoped rule'); // The scoped rule should win due to proximity. style.textContent = `${scoped_rule} ${ref_rule}`; assert_equals(getComputedStyle(element).zIndex, '1', 'scoped + unscoped'); // The scoped rule should win due to proximity (reverse). style.textContent = `${ref_rule} ${scoped_rule}`; assert_equals(getComputedStyle(element).zIndex, '1', 'unscoped + scoped'); // Add one (1) to the specificty of the unscoped rule. This should // cause the unscoped rule to win instead. style.textContent = `div${ref_rule} ${scoped_rule}`; assert_equals(getComputedStyle(element).zIndex, '2', 'unscoped + scoped'); }, format_scoped_rule(scoped_selector, '') + ' and ' + ref_selector); } // Selectors within @scope implicitly have `:scope <descendant-combinator>` // added, but no specificity associated with it is added. // See https://github.com/w3c/csswg-drafts/issues/10196 test_scope_specificity(['@scope (#main)', '.b'], '.b'); test_scope_specificity(['@scope (#main) to (.b)', '.a'], '.a'); test_scope_specificity(['@scope (#main, .foo, .bar)', '#a'], '#a'); test_scope_specificity(['@scope (#main)', 'div.b'], 'div.b'); test_scope_specificity(['@scope (#main)', ':scope .b'], '.a .b'); // & behaves like :where(:scope) - No specificity is added. // See https://github.com/w3c/csswg-drafts/issues/9740 test_scope_specificity(['@scope (#main)', '& .b'], ':where(#main) .b'); test_scope_specificity(['@scope (#main)', 'div .b'], 'div .b'); test_scope_specificity(['@scope (#main)', '@scope (.a)', '.b'], '.b'); // Explicit `:scope` adds specficity. test_scope_specificity(['@scope (#main)', ':scope .b'], ':scope .b'); // & behaves like :where(:scope), even for implicit scope roots. test_scope_specificity(['@scope', '& .b'], ':where(:scope) .b', styleImplicit); // Using relative selector syntax does not add specificity test_scope_specificity(['@scope (#main)', '> .a'], ':where(#main) > .a'); </script>