I am trying to migrate some Vue.js Single File Components from ::v-deep
syntax to :deep()
, as described here. However, I am not sure how to make it work with nested SCSS rules with &__*
. Rules without &__*
work just fine.
The SCSS compiler we use is dart-sass.
Example
For example, having this original snippet:
::v-deep .wrapper {
display: flex;
&__element {
display: block
}
}
Correctly compiles the code to
[data-v-S0m3Ha5h] .wrapper__element {
display: block;
}
And throws a warning: [@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead.
:deep()
in top-level rule
I have tried converting it to :deep()
like this:
:deep(.wrapper) {
display: flex;
&__element {
display: block
}
}
which results in a compiler error, because :deep(wrapper)__element
is not a valid selector.
:deep()
in the nested rule
So I moved the :deep
to the nested rule:
.wrapper {
display: flex;
:deep(&__element) {
display: block
}
}
which compiles without errors, but produces botched css:
.wrapper[data-v-S0m3Ha5h] &__label {/* ... */}
Question
How can I use nested &__*
rules with :deep()
?
CodePudding user response:
Sass apparently doesn't allow the selector argument list of :deep
(or of any other pseudo-class) to be nested because of the reason you mentioned, but there are a couple workarounds.
Workaround 1: Split up the Sass styles
Split up the styles so that :deep
's selector list is not nested:
<!-- MyParent.vue -->
<style scoped lang="scss">
:deep(.wrapper) {
display: flex;
}
:deep(.wrapper__element) {
display: block;
}
</style>
Workaround 2: Split up the class names
Break up the BEM class names (from wrapper__element
to __element
) so that parent selectors are not necessary:
<!-- MyComponent.vue -->
<template>
<div >
<div >...</div>
</div>
</template>
or augment wrapper__element
with an additional __element
class (if you can ignore the repetition):
<!-- MyComponent.vue -->
<template>
<div >
<div >...</div>
</div>
</template>
For some reason, this scenario requires :deep
to based on a selector (e.g., root
in the example below):
<!-- MyParent.vue -->
<template>
<div >
<MyComponent />
</div>
</template>
<style scoped lang="scss">
.root:deep(.wrapper) {
display: flex;
.__element {
display: block;
}
}
</style>
<!-- MyComponent.vue -->
<template>
<div >
<h1>.wrapper</h1>
<!-- Add __element class here