SVG class selector matches below an @scope limit
Categories
(Core :: CSS Parsing and Computation, defect)
Tracking
()
People
(Reporter: mdleichty, Unassigned)
Details
Attachments
(2 files)
A scoped class rule styles an SVG rect below the scope limit. The same standalone HTML gives the expected result in Chromium 153.0.8010.12 and WebKit 26.6. Tested on macOS with Playwright’s Firefox 155.0 (headless). I have not yet reproduced it in an unmodified release/Nightly installation.
Steps to reproduce:
- Save and open this standalone HTML (no framework or JavaScript is required):
<!doctype html>
<style>
@scope ([data-component~="x-a"]) to ([data-slotted]) {
*.shape { fill: rgb(1, 2, 3); }
}
</style>
<div data-component="x-a">
<svg><rect class="shape"></rect></svg>
<svg id="projected" data-slotted><rect class="shape"></rect></svg>
</div>
- In the console, run:
[...document.querySelectorAll("rect")].map(el => getComputedStyle(el).fill)
Expected: ["rgb(1, 2, 3)", "rgb(0, 0, 0)"]. The second SVG is the scope limit, so neither it nor its rect should match the scoped rule. There is no fill rule on any ancestor from which the second rect could inherit this value.
Actual in the tested Firefox build: ["rgb(1, 2, 3)", "rgb(1, 2, 3)"]. Chromium and WebKit return the expected result.
Changing *.shape to .shape, rect.shape, or *:is(.shape) also reproduces the failure. It was discovered while testing stylesheet-local namespaces, but the reduced case above uses no @namespace.
I searched the existing @scope bugs. Bug 1889109 concerns scope/style sharing but is resolved fixed; I did not find an open report with this SVG boundary case. This report does not assume the cause is style sharing.
Both rectangles deliberately share the same class. The first is inside the scope; the second is below the excluded SVG boundary. Only the first should receive the fill rule. The attachment adds explanatory HTML comments without changing the tested selectors or element structure.
Additional observation and CSS workaround, tested with the same Playwright Firefox 155 build:
Appending this rule to the attached reproduction changes the computed fills from ["rgb(1, 2, 3)", "rgb(1, 2, 3)"] to the expected ["rgb(1, 2, 3)", "rgb(0, 0, 0)"]:
[data-slotted] { --html-next-scope: slot; }
The scoped selector and DOM stay unchanged; only an unused inherited custom property differs at the excluded boundary. This supports a style-reuse explanation, but I have not traced Firefox internals to establish the cause.
We have implemented a component-tooling workaround in https://github.com/nextwebwg/html-next/pull/205. It uses one private inherited marker with distinct component-root, projection and nested-boundary values under @supports (-moz-appearance: none). Private root/projection declarations use priority so author layers cannot override the boundary reset. Common rules are delivered once outside import conditions. It does not reset author fill or other inherited properties and adds no observer or element ownership attributes.
Regression checks passed in Chromium, Firefox and WebKit for conflicting namespaces, nested/empty components, resolved host conditions, explicit deep slot styling, layered imports and DOM moves. Real Svelte mount/hydration and Vue conversion cases also passed. This is an application/compiler workaround; the independent native fixture still reproduces the browser defect.
Comment 3•7 days ago
|
||
Updated•7 days ago
|
Comment 4•7 days ago
|
||
I believe this is a duplicate of bug 2075194, works for me on nightly.
Description
•