29

I'm working on the VueJS 2 project and I'm trying to clean the code but struggle with scoped styling.

Here is my requirements. :)

I have 3 components those are very similar to each others, so I decide to use mixins to merge the code into one file. Each component will use that mixins of both template and vuejs. When I want to customize the conditions of a particular component, I can simply override the code in it and it is working fine in this part.

However, one thing that I want to do more is to move the scoped style to the mixins as well. At the moment, the style is wrapped in <style lang="scss" scoped></style> tag and this style works very well on its component but I have to duplicate the styling codes into all 3 components.

I know I can add these styles to the global css file but I don't want some styles to the global scope, only one these 3 components will apply for these.

Is it any way to add these styles and apply to mixins?

What is the best practice to code this particular case?

4 Answers 4

27

Vue makes this easy.

Solution

To use shared styles in a component you can do this.

MyComponent.js

<template>
</template>

<script>
</script>

<style lang="scss" scoped>
  @import '@/scss/shared-styles.scss';
  @import 'styles.scss'; // this is the regular CSS used just by the component
</style>

Alternative

You can also import the shared CSS files in the component CSS file instead like below.

MyComponent.js

<template>
</template>

<script>
</script>

<style lang="scss" scoped>
  @import 'styles.scss';
</style>

styles.scss

@import '@/scss/shared-styles.scss'

// rest of your component CSS

Automatically import global styles

If you want certain styles to be available in ALL your components you can do this.

vue.config.js

module.exports = {
  ...
  css: {
    loaderOptions: {
      sass: {
        prependData: `
          @import "@/scss/global.scss";
        `
      },
    },
  },
}
Sign up to request clarification or add additional context in comments.

4 Comments

This should be the accepted answer.. :) also is it not possible to import css files ? do i have to rename it to .scss for it to work for < style scoped > tag ?
Hi - yes, this is possible. Just remove the lang="scss" attribute: <style scoped>.
This doesn't work for me when using a multi page application. I am using bootstrap, and it gets imported several times.
Yeah, I don't think the scoped piece works right. The styles that I @import are showing up globally for me (which I don't want).
8

I just found out the scoped style also affect on the child components as well.

Therefore, I found the solution, not sure is it the best practice but I feel very nice for it.

Create a WrapperComponent and I put the scoped style here and a small template.

<template>
    <div>
        <slot></slot>
    </div>
</template>

<style lang="scss" scoped>
    /* css style that will apply to all children */
</style>

What happen here is that, when we wrap whatever components with this WrapperComponent, the template will pass on the HTML via slot without any modification and style will be able to apply from now on.

In mixins, I import this wrapper and wrap the component template with the WrapperComponent. Here is the example.

import WrapperComponent from './WrapperComponent'

let MyMixins = {

    template: `<wrapper-component>
        <div>
            Whatever HTML code here
        </div>
    </wrapper-component>`,


    components: {
        WrapperComponent,
    },
};

When we use this mixins or a child component, the style from WrapperComponent will be automatically applied and also can be used with other groups of components those want to use the same parent style.

2 Comments

You cannot use <slot /> as component root element because it may contain multiple nodes. Apart from that this approach does work.
This isn't working with scoped for me (without scoped is works, but I need scoped styles)
3

Perhaps use modules instead of setting up a style section with a scoped attribute.

https://vue-loader.vuejs.org/en/features/css-modules.html

This way your CSS will still be scoped and not part of your global styling.

1 Comment

CSS Modules works doesn't serve my needs. It just like to add another level of css but can be one good option to go.
1

I just dropped my fadeTransition.css file into my vue app /assets folder, and import like this:

<template>
  <transition name="fade">
    <div v-if="showContent">test</div>
  </transition>
</template>
<script>
  import '@/assets/fadeTransition.css';
  // component definition
</script>

fadeTransition.css

/* fade menus in, not out */
.fade-enter-active {
  transition: opacity .5s;
}
.fade-enter {
  opacity: 0;
}

Clean and simple. Should work for scss, too.

Cheers!

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.