Description
Vue version
3.5.13
Link to minimal reproduction
Steps to reproduce
Block One
-
In
App.vue
we set thebackgroundColor
prop to a value oflightgray
. -
Inspect the rendered HTML of "Block One" and notice the value of the
background-color
prop is bound to the rootdiv
element via an inline CSS Custom Property, prefixed by a generated hash, e.g.style="--a4f2eed6-backgroundColor: lightgray;"
-
Notice the hash is also bound to the
data-v-a4f2eed6
attribute (for scoped styles) as well. -
Inspect the
Styles
panel in the browser, and notice the.block
class for "Block One" refers to the same CSS Custom Property for thebackground-color
property (prefixed in this example with--a4f2eed6-
)
Block Two
- In
App.vue
we do not set thebackgroundColor
prop for Block Two in the component props, meaning it utilizes the prop default value ofnull
(to prevent the property from being bound to the component since it is not desired for this instance) - Notice the hash (for scoped styles) of Block Two is the same as Block One (i.e.
data-v-a4f2eed6
). - Inspect the
Styles
panel in the browser, and notice the.block
class for "Block Two" refers to the same CSS Custom Property for thebackground-color
property (prefixed in this example with--a4f2eed6-
), rather than generating its own hash to attempt to use for the property.
Block Three
- Since the CSS custom property is not defined on a parent node of Block Three, there is no issue in its display.
What is expected?
"Block Two" (as referenced in the Steps to reproduce) should generate its own CSS custom property hash prefix (likely corresponding to the scoped styles hash as well) that is then utilized inside its style rule.
<div data-v-a4f2eed6="" id="v-0" class="block" style="--a4f2eed6-backgroundColor: lightgray;">
<div>Block One</div>
<div data-v-a4f2eed6="" id="v-1" class="block">
<div>Block Two</div>
</div>
</div>
I would expect the generated CSS in the scenario described to evaluate to this:
/** Block One */
.block {
&[data-v-a4f2eed6] {
background-color: var(--a4f2eed6-backgroundColor);
}
}
/** Block Two */
.block {
&[data-v-a4f2eed6] {
background-color: var(--DIFFERENT_HASH-backgroundColor);
}
}
What is actually happening?
Since instances of the same component share the same generated hash for both the scoped styles as well as generated CSS custom properties, the CSS background-color
cannot be explicitly "unset" by providing a null
prop value for a secondary, nested instance of the same component.
The result of this means that in order for the child component to not reference the CSS Custom Property of its parent, you have to explicitly set the default prop value that is mapped to v-bind to something that essentially "unsets" the value that may be present from the parent.
Using the example from the reproduction, to solve the issue, I would have to change the defineProps
implementation to set the backgroundColor
prop to initial
(i.e. a reset), or alternatively pass a value of something like transparent
which isn't ideal.
const { backgroundColor = 'initial' } = defineProps<{ backgroundColor?: string }>()
This will then set the value of the same CSS Custom Property, on the child node, to initial
<div data-v-a4f2eed6="" data-v-7ba5bd90="" id="v-0" class="block" style="--a4f2eed6-backgroundColor: lightgray;">
<div data-v-7ba5bd90="">Block One</div>
<div data-v-a4f2eed6="" data-v-7ba5bd90="" id="v-1" class="block" style="--a4f2eed6-backgroundColor: initial;">
<div data-v-7ba5bd90="">Block Two</div>
</div>
</div>
System Info
No response
Any additional comments?
Generating a separate hash for each instance of a component (rather than reusing the same one for each one) would obviously lead to a lot of bloat in the injected DOM styles, especially for instances where this behavior doesn't exist.
I'm unsure if having to explicitly provide a "reset" value makes sense either, as it will bloat the inline style
rules on every top-level component DOM element to set and/or reset the value.