Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Star selectors leak scoped styles into children #12906

Open
thecodewarrior opened this issue Feb 18, 2025 · 0 comments · May be fixed by #12918
Open

Star selectors leak scoped styles into children #12906

thecodewarrior opened this issue Feb 18, 2025 · 0 comments · May be fixed by #12918
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: sfc

Comments

@thecodewarrior
Copy link

Vue version

3.5.13

Link to minimal reproduction

https://play.vuejs.org/#eNqNUtFOwjAU/ZWmLyQGNwn6gpNEDSb6oEZ8bGLmeoFi1zZtN2YI/+5t5wAjGt52zz09O/fes6bXxiR1BXREM1dYYTxx4CszZkqURltPbnVpyMzqkvSSNBSB3rtkKkvbB0jFwkNpZO4BK0IyLmpSyNy5K0ZXesVohLERBNLfRZbiC/zK0j0dLJ3/lEBcoQ3wSExQjZyMZsI6f1oshORk3aq9a8vBjsjANMRpKTixwNEmIZvoNSiNaZ96VFMzMU+WTiscOz5ntEAvQoJ9Ml5o5RgddcKM5lLq1UPEvK2g3+HFAoqPA/jSNQFj9NmCA1sDo9uez+0cfNueTB+hwe9ts9S8ksj+p/kCOFwVPLa0m0pxtL3Hi27v4/GEmr+6SeNBuW6oYDQuJfIZxWOGM/w1+s7uMDn/XuYGt9gF4UBujs2FUCr47sIQAnAXztplYYtOAS/Gd/CRYUniD9pRTM45LgPTcWYaDMXPSLzVYMOCcJhhcpEMhnTzBXDwBpE=

Steps to reproduce

  • Create a component Foo
    • Add class="foo" on the root element
    • Add a scoped style .foo * { border: 1px solid red; }
  • Create a component Bar
    • Create multiple nested elements (not just a root element)
  • Add <bar/> into Foo's root

What is expected?

The star selector should be scoped to inside Foo

What is actually happening?

The star selector isn't being scoped, which causes the styles to leak into child elements

System Info

Any additional comments?

The example provided includes a :first-child pseudo-class, which makes the behavior (and use case) a bit clearer, however the scoping issues occur regardless of whether the pseudo-class is specified.

We ran into this issue while attempting to upgrade from Vue 2 to Vue 3, where certain selectors that used to be scoped to immediate children were suddenly applying to deep children. The usage sites themselves were flawed in other ways, and should have been using direct child combinators, but those are workarounds and shouldn't be necessary for scoping to apply correctly.

In the past Vue 3 used to mirror Vue 2's behavior, which scopes only the star selector. (Vue 2 demo). That behavior itself isn't ideal, which was reported in #10548 and then addressed in #10551, however in doing so it caused the styles to leak to children instead of from parents. More manageable, but still not ideal.

Here's a sample of different selectors and how they compile in Vue 2 vs Vue 3 ([--] represents the scoping attribute selector)

Source                Vue 2                     Vue 3
:active               [--]:active               [--]:active
*:active              *[--]:active              [--]:active
.foo :first-child     .foo[--] :first-child     .foo[--] :first-child
.foo *                .foo *[--]                .foo[--] *
.foo *:first-child    .foo *[--]:first-child    .foo[--] *:first-child

The solution for this would be to scope both the final class selector and the star selector:

Source                Vue 3 (fixed)
:active               [--]:active
*:active              [--]:active
.foo :first-child     .foo[--] :first-child
.foo *                .foo[--] [--]
.foo *:first-child    .foo[--] [--]:first-child

Ideally the bare pseudo-class (.foo :first-child) would be fully scoped too, but if the goal is parity with Vue 2, that's not necessary.

Also the ticket that started this, #10548, isn't actually running into a fundamental scoping issue caused by star selectors. The same thing applies to any non-direct-child combinators (demo), but in their case the star selector made it difficult to manage. The only way to solve the fundamental scoping issue would be to add the scope attribute to every level of the selector (.foo .bar :first-child -> .foo[--] .bar[--] [--]:first-child), but I'm guessing that has an adverse performance impact, otherwise it likely would have done that from the start.

@edison1105 edison1105 added scope: sfc 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: sfc
Projects
None yet
2 participants