Closed Bug 2080046 Opened 8 days ago Closed 7 days ago

SVG class selector matches below an @scope limit

Categories

(Core :: CSS Parsing and Computation, defect)

Firefox 155
defect

Tracking

()

RESOLVED DUPLICATE of bug 2075194

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:

  1. 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>
  1. 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.

Attachment #9656530 - Attachment filename: file_2080046.txt → firefox-svg-scope.html
Attachment #9656530 - Attachment mime type: text/plain → text/html

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.

Attachment #9656874 - Attachment mime type: text/plain → text/html

I believe this is a duplicate of bug 2075194, works for me on nightly.

Status: UNCONFIRMED → RESOLVED
Closed: 7 days ago
Duplicate of bug: 2075194
Resolution: --- → DUPLICATE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: