component-compiler-utils
component-compiler-utils copied to clipboard
:root Selector should not be scoped
The :root CSS pseudo-class matches the root element of a tree representing the document, it identical to the selector html usually.
But a scoped :root selector dose not match any Element.
With a demonstration which created by @vue/cli 4.0.5:
<!--HelloWorld.vue-->
<style scoped>
:root {
--font-color: red;
}
h3 {
color: var(--font-color);
}
</style>
And we got:
<style type="text/css">
[data-v-469af010]:root {
--font-color: red;
}
h3[data-v-469af010] {
color: var(--font-color);
}
</style>
h3's font-color wont change, it still inherits from parent element rather than red.
How to resolve?
Scoped :root does not match any element, but a attribute selector with :root do. So, we can get the expected result if changing:
[data-v-469af010]:root { /*balabala*/ }
to
/* proposal A: */
:root { /*balabala*/ }
/* or */
/* proposal B: */
:root [data-v-469af010] { /*balabala*/ }
I prefer proposal B that will make sure the scoped style rendered as wished. Such as:
<!-- HelloWorld.vue -->
<template>
<h3>Hello</h3>
</template>
<style scoped>
:root {
--font-color: red;
}
h3 {
color: var(--font-color);
}
</style>
<!-- another unscoped style in HelloWorld.vue-->
<style>
:root {
--font-color: blue;
}
</style>
We will get some css code like this:
<style type="text/css">
:root [data-v-469af010] {
--font-color: red;
}
h3[data-v-469af010] {
color: var(--font-color);
}
</style>
<style type="text/css">
:root {
--font-color: blue;
}
</style>
h3 will rendered with red font color as expected.
I'll create a PR if this issue is logical.
After noticing the current behaviour I came here with the intention of fixing this. Happy to see you've already submitted a PR :+1:
I would question whether the :root selector should remain in the compiled CSS. Surely it is superfluous and can be removed leaving just the attribute selector:
<!-- HelloWorld.vue -->
<template>
<h3>Hello</h3>
</template>
<style scoped>
:root {
--font-color: red;
}
h3 {
color: var(--font-color);
}
</style>
<!-- another unscoped style in HelloWorld.vue-->
<style>
:root {
--font-color: blue;
}
</style>
Would compile to:
<style type="text/css">
[data-v-469af010] {
--font-color: red;
}
h3[data-v-469af010] {
color: var(--font-color);
}
</style>
<style type="text/css">
:root {
--font-color: blue;
}
</style>
Additionally, I'd like to pre-empt a potential objection to this change which might be something like "You should just use `*` or `::v-deep` instead of `:root`." Consider a .scss file from a 3rd party library that uses the `:root` selector which I want to `@import` within a scoped style block in my component(s). Example:
// styles.scss
:root {
--font-color: red;
}
<!-- HelloWorld.vue -->
<template>
<h3>Hello</h3>
</template>
<style scoped>
@import "styles.scss";
h3 {
color: var(--font-color);
}
</style>
Should compile to:
<style type="text/css">
[data-v-469af010] {
--font-color: red;
}
h3[data-v-469af010] {
color: var(--font-color);
}
</style>