Skip to content

Scoped style attribute not attached to selector key if it's a pseudo-class/element #8868

Open
@kleinfreund

Description

@kleinfreund

Vue version

3.3.9

Link to minimal reproduction

https://play.vuejs.org example

Steps to reproduce

  1. Create a scoped style block.
  2. Add a rule set with a selector which has any ancestor selectors and a bare pseudo-class (but not :is() or :where()) as the key (e.g. div :not(.test) not div *:not(.test)).

Example:

<style scoped>
div :not(.test) {
  color: tomato;
}

div :required {
  color: tomato;
}

/* workaround: add `*` to the pseudo class */
div *:required {
  color: tomato;
}
</style>

What is expected?

The generated CSS rule set's selector list is scoped to the key of the selector (i.e. div [data-v-7ba5bd90]:not(.test)) even if the key is a bare pseudo-class or pseudo-element (except in the case of :deep).

div [data-v-7ba5bd90]:not(.test) {
  color: tomato;
}

div [data-v-7ba5bd90]:required {
  color: tomato;
}

div *[data-v-7ba5bd90]:required {
  color: tomato;
}

What is actually happening?

The generated CSS rule set's selector list is scoped to the last selector part that is not a bare pseudo-class (i.e. div[data-v-7ba5bd90] :not(.test)).

div[data-v-7ba5bd90] :not(.test) {
  color: tomato;
}

div[data-v-7ba5bd90] :required {
  color: tomato;
}

div *[data-v-7ba5bd90]:required {
  color: tomato;
}

This leads to styles unintentionally leaking out of the scoped tree.

System Info

Binaries:
    Node: 19.1.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD
    npm: 9.8.0 - ~\dev\package\node_modules\.bin\npm.CMD
    pnpm: 8.5.1 - C:\Program Files\nodejs\pnpm.CMD
  Browsers:
    Edge: Spartan (44.22621.1992.0), Chromium (115.0.1901.183)
    Internet Explorer: 11.0.22621.1

Any additional comments?

  • This seems to be true for most pseudo-classes and pseudo-elements, but isn't true for :is(), :where(), and the special case :deep()
  • Initially posted as a question here: Should "div :is(*)" in a scoped style block produce a different selector? #8800
  • The current behavior is unexpected to me when writing scoped styles as it easily allows styles to leak out of the scoped tree (e.g. when using slots)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions