diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts
index 907b299b824..12e67822697 100644
--- a/packages/runtime-dom/__tests__/customElement.spec.ts
+++ b/packages/runtime-dom/__tests__/customElement.spec.ts
@@ -886,6 +886,39 @@ describe('defineCustomElement', () => {
assertStyles(el, [`div { color: blue; }`, `div { color: red; }`])
})
+ test('child components styles should before parent styles', async () => {
+ const Baz = () => h(Bar)
+ const Bar = defineComponent({
+ styles: [`div { color: green; }`],
+ render() {
+ return 'bar'
+ },
+ })
+ const WrapperBar = defineComponent({
+ styles: [`div { color: blue; }`],
+ render() {
+ return h(Baz)
+ },
+ })
+ const WBaz = () => h(WrapperBar)
+ const Foo = defineCustomElement({
+ styles: [`div { color: red; }`],
+ render() {
+ return [h(Baz), h(WBaz)]
+ },
+ })
+ customElements.define('my-el-with-wrapper-child-styles', Foo)
+ container.innerHTML = ``
+ const el = container.childNodes[0] as VueElement
+
+ // inject order should be child -> parent
+ assertStyles(el, [
+ `div { color: green; }`,
+ `div { color: blue; }`,
+ `div { color: red; }`,
+ ])
+ })
+
test('with nonce', () => {
const Foo = defineCustomElement(
{
diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts
index f0724663090..6ee67745810 100644
--- a/packages/runtime-dom/src/apiCustomElement.ts
+++ b/packages/runtime-dom/src/apiCustomElement.ts
@@ -229,7 +229,7 @@ export class VueElement
private _connected = false
private _resolved = false
private _numberProps: Record | null = null
- private _styleChildren = new WeakSet()
+ private _styleChildren = new WeakMap()
private _pendingResolve: Promise | undefined
private _parent: VueElement | undefined
/**
@@ -596,18 +596,25 @@ export class VueElement
owner?: ConcreteComponent,
) {
if (!styles) return
+ const styleElements: HTMLStyleElement[] = []
if (owner) {
- if (owner === this._def || this._styleChildren.has(owner)) {
+ if (owner === this._def) return
+ const existingStyles = this._styleChildren.get(owner)
+ if (existingStyles) {
+ // move existing styles to the top
+ this.shadowRoot!.prepend(...existingStyles)
return
}
- this._styleChildren.add(owner)
+ this._styleChildren.set(owner, styleElements)
}
+
const nonce = this._nonce
for (let i = styles.length - 1; i >= 0; i--) {
const s = document.createElement('style')
if (nonce) s.setAttribute('nonce', nonce)
s.textContent = styles[i]
this.shadowRoot!.prepend(s)
+ if (owner) styleElements.unshift(s)
// record for HMR
if (__DEV__) {
if (owner) {