Open
Description
Vue version
3.3.9
Link to minimal reproduction
https://play.vuejs.org example
Steps to reproduce
- Create a scoped style block.
- 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)
notdiv *: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)