Subscribe on changes!

Scoping does not work as expected when using :is and :where selectors in Vue 3.3.9

avatar
Nov 29th 2023

Vue version

3.3.9

Link to minimal reproduction

https://play.vuejs.org/#eNqVVd1uEz0QfZXRXn2gZFf6EBKE8lcEElwAAsQF2hvv7mRj6rWNPZukVH13jr1JkxaKihJF9njG58yZGeeieOl9uR65WBQnsQ3aC0WW0T+rrR68C0JvnKNlcAPVRVlhk7zrorYn1eQPT2yEB2+UMHZEJ51e5wWWKbyarNVkPqmunItZMaHMB+XL79FZ8LhIzvXuINbFgrIl2TL0AouViI+Lqmo7i7COjV6H0rJU1g/VC7hVYbSiB553bnjxoHxQPgZ6lGNzyXGYN8FtIofSB9fhprqYHWFVOFlzmAe2HQcOd8W+EXaMf+PoGocEn9Ava3sJZSS2zi51f0OX1g1eGw4fvGhnr+ujjHGbd9kmYeSrXNoVt2d/sH+P2ymnj4Ezs6P8RYWeZTp+/fk9b7G+OhxcN5pdLW45/MTRmTFxnNxOR9uB9pFfZvs2l1nb/kt8vRW2cZ9UIprVyP65Hq/+kvqBLtQ+UnHXsbf396kKh/7G5h/7G0tqjYrxaV0snauLZ/jdt3r2SAC3TkC+PMq5YUK5PXewlLhhRmWDuAuq7tOpkxUlIynbTXYVmNCynoM53wWSOJKVjpQaxFm2UtL9KsE2qj3rg4P+C/Jj8IafQJuEvNis0IX/HQDvTYjfODiKnlu91K2W8xl1jiNZJ6S8N9g3owCNMxhK0pEbxcMG/KgGJhVpo0F7AcPvLBozHjjo+DuBnCRCeQsSMiXXMAWsGhUTnKWsWiRtUwlT1Q6ZT/wQ3wdmS2NEf9FXeORJ/AOh7LdnBPy39sr90SR9j9yT0OmmTokiJRI0YHiWKBwuX8lg/uKdwYHwJZUKX1SxMTwo0S1x2ZeEkuwZexeljXHeqXA2h9p4t3Kr7Q/Im7EH+NIFWql1ChkcOgPvhgRnyOGpIaP7lVTpilSwAXRry1uF/mPAqJ4p9cACvKdnLQp0aYyWnyX0rLjTUvUo5djMN8P/mx8P58uzn10/Pl+i7k/RDln6lNWum5IA9ybRLoB1XejMpg/qfBIbQ5aqmP4IdkVMg3qnYUOHYNjwexi2u85XnqybzNBb1zml0PQpLn8BGiNv0g==

Steps to reproduce

There is text "foo" with green background and text "bar" with green background. The associated styles are in Foo.vue component.

What is expected?

The text "foo" is expected to have lightgray background and the text "bar" to have red background, as it have if one use Vue version 3.3.8.

What is actually happening?

There was a pull request https://github.com/vuejs/core/pull/8929 which fixed https://github.com/vuejs/core/issues/8915 but it introduced issues with scoping.

When there is :is or :where selector in a rule, Vue seems to now scope the first selector only.

Example 1

:is(.foo, .bar) -> only .foo is scoped

Example 2

:where(html .foo) -> .foo is scoped which is expected

Example 3

:where(html) .foo -> html is scoped instead of .foo

System Info

System:
    OS: Linux 6.5 Pop!_OS 22.04 LTS
    CPU: (20) x64 13th Gen Intel(R) Core(TM) i7-1370P
    Memory: 3.66 GB / 31.03 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 20.9.0 - /run/user/1000/fnm_multishells/115870_1701167364483/bin/node
    npm: 10.1.0 - /run/user/1000/fnm_multishells/115870_1701167364483/bin/npm
    pnpm: 8.11.0 - ~/.local/share/pnpm/pnpm
  Browsers:
    Chrome: 119.0.6045.159

Any additional comments?

My original use case and how I discovered this behavior was by using a postcss plugin that helps you with setting light or dark theme using a class on html element. It allows one to write prefers-color-scheme: dark media queries but enable overriding it by using .is-light and .is-dark classes on the html element. It has to use :where pseudo selector in order to not increase the specificity of affected selectors.

Here is an example: https://stackblitz.com/edit/github-wm2wq5-fkzdgu?file=app.vue In the example there is text "foo" which is expected to be green, not red, for prefered theme dark.

avatar
Dec 4th 2023

Awesome, you guys are fast!