Subscribe on changes!

Parent component scoped style overrides child component root tag's style

avatar
Jan 12th 2023

Vue version

v3.2.45

Link to minimal reproduction

SFC Playground

Steps to reproduce

No

What is expected?

Child component‘s background-color be green.

What is actually happening?

Child component‘s background-color be gray.

System Info

No response

Any additional comments?

The current performance conforms to the code logic, but does not conform to the use logic. I provide an inelegant workaround in the reproduction, but I hope this problem can be really solved.

avatar
Jan 12th 2023

Thats intended and documented as such. Yes, sometimes workarounds are necessary in edge cases. But more often than not, you want this to be able to i.e. position a child component with css.

avatar
Jan 14th 2023

@LinusBorg Sorry for missing that doc.

the parent can style the child root element

I think the above design violates the following principle:

its CSS will apply to elements of the current component only.

In fact, the current behavior has made a mess.

But more often than not, you want this to be able to i.e. position a child component with css.

Your example is indeed more common at present, and it is acceptable to violate the principles because of convenience, because quantity affects quality.

But your use case is more common seems to be a side effect of this wrong design.

Here is a modular layout use case that uses a simple but flawed workaround: adding a signature class. The defect is unable to guarantee the uniqueness of the signature, which is unacceptable to the modularity.

You may notice that there uses a generic class name .wrapper, instead of the class name with the same name as the component, for following reasons:

  • DRY: component rename free
  • uniformity: extract the layout class and use a consistent class name

When this problem is solved, the above modular layout use cases can also become more common.

If you agree with the above, here are some ideas about implementation and migration:

Implementation

  1. Add a special data-v-[hash:comp] attribute to the component root element to replace the original data-v-[hash] attribute. (can components and elements be distinguished?)
  2. Add a selector :deep-root() (or :scope(), aligns with the pseudo-class :scope) that matches the root element of the child component.

input:

<template>
  <Comp class="example" />
</template>

<style scoped>
  :deep-root(.example) {
    color: red;
  }
</style>

<script setup>
import Comp from './Comp.vue'
</script>
// Comp.vue
<template>
  <div>Component</div>
</template>

output:

<template>
  <div 
    class="example" 
-   data-v-[hash]
+   data-v-[hash:comp]
  >Component<div/>
</template>

<style>
  .example[data-v-[hash:comp]] {
    color: red;
  }
</style>

migration

This is a breaking change that will need to be released in the next major release unless provide a compatible way (such as adding configuration to control this behavior).

avatar
Jan 20th 2023

Today I've spent much time troubleshooting this feature. @LinusBorg Is this intended peculiarity stated somewhere in the docs regarding the scoped styles?