4

Is it possible to work with nested css selectors when using vuejs css modules?

For example, I want to scope this css (so that id does not affect child components):

.list {
    ...

    .item {
       ...
     }
}

In the documentation I could see only not-nested examples, but is it at all convenient, since I'll need then name them like .list-item which resembles BEM. But if I use BEM there is no point in using css modules, is there?

1
  • this looks like a combination of scss and scoped? Commented Nov 1, 2018 at 1:57

3 Answers 3

6

Yes, it's possible to work with nested css selectors so they will not affect child components; use css modules.

You need to use a preprocessor to enable nesting, either LESS or SASS.

If using Single File Components your component would look something like this

<template>
  <ul :class="$style.list">
    <li :class="$style.item"></li>
  </ul>
</template>

<!--       Or lang="less" -->
<style module lang="scss">
.list {
    ...

    .item {
       ...
     }
}
</style>
Sign up to request clarification or add additional context in comments.

5 Comments

How can you use the $style. in class? I tried to used that but the class name doesn't appear when render.
@user3779015 Have you added module to the <style> tag?
Yes, this is my style - <style module lang="scss">. Did you do any configuration on webpack? cuz it seems like when I used the lang="scss", i cannot used the $style in class.
As the OP referenced the vue loader docs it seemed unncessary to point out that this should be configured beforehand :-)
I was wondering if you can help me with my webpack config? I tried to add the configs from vue-loader website but it didn't work. Here is the link of my problem.
2

Yes, nesting css selectors is called using scss. You will have to setup scss.

Example make your style tag in the vue component:

<style scoped lang="scss">

The scoped attribute tells it to apply only to this component.

In regards to bem you can do stuff like this in scss:

.list {
   //styles-a

   &-item {
      //styles-b
   }
}

which will convert to this in css:

.list {
    //styles-a
}
.list-item {
    //styles-b
}

1 Comment

This answer doesn't take into account that OP asked about CSS Modules (<style module lang="scss">)
1

If you want, for example, override CSS class of some UI library in Vue you can use :global keyword. Let's say you have a n-dropdown component from Naive UI library. And you want to customize it with overriding its native very deeeeeply nested n-dropdown-option-body__prefix--show-icon CSS class only in current component using CSS modules. Here is how you can do it:

<template>
    <n-dropdown :class="$style.menu">
    </n-dropdown>
</template>

<style module>
.menu:global.n-dropdown-menu .n-dropdown-option .n-dropdown-option-body .n-dropdown-option-body__prefix.n-dropdown-option-body__prefix--show-icon {
    margin-left: 33px;
    margin-right: 19px;
}
</style>

In the end you will get selector which looks something like this

.MobileNavMenu_menu_NhSka.n-dropdown-menu .n-dropdown-option .n-dropdown-option-body .n-dropdown-option-body__prefix.n-dropdown-option-body__prefix--show-icon {
    margin-left: 33px;
    margin-right: 19px;
}

So all classes after :global keyword will be untouched by module manipulations.
If .n-dropdown-menu should be a child of menu then :global should have a whitespace from both sides: .menu :global .n-dropdown-menu
Vue will remind you about it with horrible crash

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.