Subscribe on changes!

Deep selectors don't work if child component has multiple root elements

avatar
Oct 12th 2022

Vue version

3.2.40

Link to minimal reproduction

https://sfc.vuejs.org/#eNqVUkFOwzAQ/IrxpSA1NgFOIaqKuPADLrmUeKGBOLbWThGq8nfWTtomBUVw88zuzo493vMHa8WuBZ7x3JVYWc8c+NauiqbS1qBnj0Zb9opGs4WQAYT2xaScTurp0JDLXpCkCHjQtt54IMRYvk1XT1DXhj0brNVFLomIhbhNns5pBLkcjRN0/qsG5kpjQcXeTAHYy216xfYBMlaa2mDGENR9ILpoJ0xRO1/y3nyiN1a8O9PQ7eNcMRRcwbODUsHpOgEXfOu9dZmUbWM/3kRptFxTTWLb+EpDooxe34obcXctVeX8mBfgdPKC5tMB0saCL0fiksgdYILQKEDA2WVnvZOFZ7UfS4eX6OgBDkH+kvtcbqraxUMfYRA5RkeUXSnoZytDMkGMWPIWhmYznIRz/ET/NDc4Sk+/aWKI+F7hbz66b2z3D40=

Steps to reproduce

See the preview in SFC playground.

What is expected?

Both child components should be affected by the deep selector rule.

What is actually happening?

The deep selector only affects the one with a single wrapping root element.

System Info

No response

Any additional comments?

No response

avatar
Oct 12th 2022

I'd call this expected behaviour fom the way scoped styles and deep selectors work.

This is the generated CSS:

[data-v-472cff63] h1 {
    color: red;
}

As you can see, it requires a parent element bearing the parent's scope-id. Parent scope ids are only applied to the (single) root element of child components (so you can style it from the parent for i.e. margins or positioning). Mutpliple-root children don't inherit that attribute.

the normal usecase would be to apply a deep rule in the context of a parent element, i.e.:

.some-parent-class :deep(h1) {

}
avatar
Oct 13th 2022

I think it's also a normal usage in my example. As a user I don't need to know about how scoped CSS works. We just expect that it works.

Mutpliple-root children don't inherit that attribute.

Why? What if we apply parent scope id to every child component even if it has multiple root elements, and we change the generated CSS to:

[data-v-472cff63] h1,  [data-v-472cff63]h1 {
    color: red;
}

so that it applies in all situations? I don't know if there are some other pitfalls or considerations.

avatar
Jan 12th 2023

A better workaround:

  ~ :deep(h1),
  :deep(h1) {
    color: red;
  }
avatar
Jan 12th 2023

A better workaround:

  ~ :deep(h1),
  :deep(h1) {
    color: red;
  }

@abitwhy That's clever but won't work if I move <Comp1> to the beginning of <template> (i.e. make it the first child)