Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Element Mode - Styles applied in wrong order #13029

Open
zaalbarxx opened this issue Mar 12, 2025 · 4 comments · May be fixed by #13030
Open

Custom Element Mode - Styles applied in wrong order #13029

zaalbarxx opened this issue Mar 12, 2025 · 4 comments · May be fixed by #13030
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: custom elements

Comments

@zaalbarxx
Copy link

zaalbarxx commented Mar 12, 2025

Vue version

3.5.13

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-pn21u36z?file=src%2Fcomponents%2FHelloWorld.vue,src%2Fcomponents%2FBox.vue,src%2FApp.vue,src%2Fmain-ce.js,index.html,vite.config.js,src%2FApp.ce.vue&terminal=dev

Steps to reproduce

Open the page and wait until load.

What is expected?

I would expect the first box to be red and the second box to be green.

What is actually happening?

The first box is red, also second is red.

Generally speaking this is something that can potentially be avoided by using CSS selector specifity. But the issue here is that the behavior is inconsistent between standard Vue app and the app bundled as web component.

Basically the issue here is that there is some "box" component which has its class="box" and some "nested" component which uses "box", but applies additional class and style. Like

Box.vue
<style scoped>
.box { background-color: red }
</style>

...
HelloWorld.vue
<style scoped>
.my-box{ background-color: green}
</style>

<template>
<Box class="my-box"></Box>
</template>

So, in normal Vue app (if you switch the mode in Vite config in example) the styles will get applied from deepest to most shallow, like Box styles will be injected into DOM and then HelloWorld styles. For CE that's not (always?) the case and styles get applied "in order", so HelloWorld gets injected before Box.

I've been trying to find some info regarding this behavior, but I only found the general PR @11517 which adds some support to web component styles. Is it something that is anyhow achievable to behave like normal Vue app ? Or is there some oversight from my side here ?

I would gladly take a look at this if I'd been given a bit of a guidance here, where approximately should I look into, is it core, or maybe compiler etc. ?

System Info

Chrome 134

Image

@coderwei99
Copy link
Contributor

I think this is normal. If you want to modify the styles of the component's internal DOM, you should use :deep().

// HelloWorld.vue
<script setup>
import { ref } from 'vue';
import Box from './Box.vue';

defineProps({
  msg: String,
});

const count = ref(0);
</script>

<template>
  <div class="warp">
    <Box class="my-box"> {{ msg }} </Box>
  </div>
</template>

<style scoped>
.warp :deep(.box) {
  background-color: green;
}
</style>

@yangxiuxiu1115
Copy link
Contributor

https://github.com/vuejs/core/blob/main/packages/runtime-dom/src/apiCustomElement.ts#L584-L595
Maybe it's due to the style's insertion strategy prepend and not adjusting the order when reusing the component

@zaalbarxx
Copy link
Author

I think this is normal. If you want to modify the styles of the component's internal DOM, you should use :deep().

// HelloWorld.vue

<script setup> import { ref } from 'vue'; import Box from './Box.vue'; defineProps({ msg: String, }); const count = ref(0); </script>
{{ msg }}
<style scoped> .warp :deep(.box) { background-color: green; } </style>

I agree to disagree here. When using standard Vue build mode like here

https://stackblitz.com/edit/vitejs-vite-egtdehw6?file=src%2Fcomponents%2FHelloWorld.vue,src%2Fcomponents%2FBox.vue,src%2FApp.vue,src%2Fmain-ce.js,index.html,vite.config.js,src%2FApp.ce.vue&terminal=dev

the styles are applied from child to parent. Like I said before, it is not something that could not be fixed on the user side (you can just add another class and do something like .my-box.__important and then CSS specifity will enforce correct styles being applied. But currently there is a difference between behavior in standard app and CE app which, I believe, should not happen in that case.
Cheers

@edison1105 edison1105 added 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: custom elements labels Mar 13, 2025
@edison1105
Copy link
Member

The behavior is inconsistent with when custom elements are not used.
see playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: custom elements
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants