6

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] &__element {/* ... */}

Question

How can I use nested &__* rules with :deep()?

1 Answer 1

3

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>

demo 1

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 class="wrapper">
        <div class="__element">...</div>
    </div>
</template>

or augment wrapper__element with an additional __element class (if you can ignore the repetition):

<!-- MyComponent.vue -->
<template>
    <div class="wrapper">
        <div class="wrapper__element __element">...</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 class="root">
        <MyComponent />
    </div>
</template>

<style scoped lang="scss">
.root:deep(.wrapper) {
    display: flex;

    .__element {
        display: block;
    }
}
</style>
<!-- MyComponent.vue -->
<template>
  <div class="wrapper">
    <h1>.wrapper</h1>

    <!-- Add __element class here 👇 (and optionally remove wrapper__element) -->
    <div class="wrapper__element __element">
      <h1>.wrapper__element</h1>
    </div>
  </div>
</template>

demo 2

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.