lusarz
lusarz

Reputation: 315

Vue.js: use CSS class for child element

I have a component v-popup.vue

<template>
  <div class="overlay">
    <div class="popup">
      <slot></slot>
    </div>
  </div>
</template>

and I want to style it from the parent, for example:

<template>
  <v-popup class="custom-popup">
    Popup content
  </v-popup>
</template>

<style>
  .custom-popup {
    padding: 20px;
  }
</style>

How can I configure v-popup.vue component to make custom-popup class to be automatically added to div.popup, not div.overlay ?

Upvotes: 6

Views: 7588

Answers (2)

johnmikelridzz
johnmikelridzz

Reputation: 340

In your v-popup.vue, you can do the following:

<template>
  <div class="overlay">
    <div :class="['popup', popupClass]">
      <slot></slot>
    </div>
  </div>
</template>

<script>
 
export default {

// Do the usual implementations here...
props: {
 popupClass: ''
}

}

</script>

Then in your parent component, you can do the following:

<template>
  <v-popup popup-class="custom-popup">
    Popup content
  </v-popup>
</template>

However, I am curious. Why not encapsulate this class inside v-popup.vue. I seldom use this design unless there will be another component sharing this class from the parent.

EDIT (per your last comment): You can use this link as a reference on how to use the $attr attribute: https://jsfiddle.net/changjoo_park/pzx08wp9/

So, in a sense, you can do the following, in your parent component

<template>
  <v-popup popup-class="custom-popup" v-bind="$attrs">
    Popup content
  </v-popup>
</template>

In your v-popup component:

<template>
  <div class="overlay">
    <div :class="['popup', $attrs.popupClass]">
      <slot></slot>
    </div>
  </div>
</template>

<script>
 
export default {

// Do the usual implementations here...

}

</script>

So, no props implementations and the class is taken directly from the $attrs object. Hope this helps! You can read more about this usage here: https://v2.vuejs.org/v2/api/#vm-attrs

Upvotes: 3

Dan
Dan

Reputation: 63059

Scoped Styles

  • Using scoped styles (in both parent and child) is a good idea and will make this solution easier.

  • Instead of creating a new custom-popup class, use a deep selector in the parent. This allows the parent to define extra styles for child components that use the same selector.

  • The deep selector looks like this: >>> unless you're using a SCSS/SASS pre-processor. Then you use ::v-deep instead.

<template>
  <v-popup>
    Popup content
  </v-popup>
</template>

<style scoped>
  >>> .popup {
    padding: 20px;
  }

  /* If using SCSS/SASS, do this instead */
  /*
  ::v-deep .popup {
    padding: 20px;
  }
  */
</style>

The child will use both its own .popup class and the one from the parent.

If you didn't use scoped styles, it would quickly become a problem if you wanted to import the child in multiple parents and use different styles each time.

Upvotes: 6

Related Questions