Home > Software engineering >  Problems with scoped styles and deep styling in vue 3
Problems with scoped styles and deep styling in vue 3

Time:09-22

Im having a lot of problems triying to style a child from parent in vue3.

In this case, i create a generic button with some css properties, and i try to customize this button from other component

Parent

<template>
  <OwnButton
    
    @ownButtonClicked="emit('accept')"
  >
    <slot> 
      ACCEPT
    </slot>
  </OwnButton>
</template>

<script setup>
import OwnButton from 'path/to/own-button.vue';

const emit = defineEmits(['accept']);
</script>

<style scoped>
.accept-button :deep(.own-button)
{
  background-color  : #4CAF50 !important;
  outline-color     : green !important;
}
.accept-button :deep(.own-button:hover)
{
  background-color: green !important;
}
</style>

Child

<template>
  <button
    
    type="button"
    @click="emit('ownButtonClicked')"
    v-on:keyup.enter="emit('ownButtonClicked')"
  >
    <slot> 
    </slot>
  </button>
</template>

<script setup>

const emit = defineEmits
([
  'ownButtonClicked'
]);
</script>

<style scoped>
.own-button
{
  background-color  : azure;
  outline-color     : lightblue;
  color             : black;
  margin            : 2px;
  padding           : 5px;
  border-radius     : 15px;
  border            : 0;
  box-shadow        : 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  outline-style     : solid;
  min-width         : 100px;
  max-width         : 150px;
}
.own-button:hover
{
  cursor: pointer;
}
</style>

I tried everything I could think of, including using :deep(button) in parent

CodePudding user response:

I think it is related to where you apply the main class.

Try to put a wrapper around like that:

<template>
  <div >
     <OwnButton
    
    @ownButtonClicked="emit('accept')"
  >
    <slot> 
      ACCEPT
    </slot>
  </OwnButton>
  </div>
 
</template>

<script setup>
import OwnButton from './Comp.vue';

const emit = defineEmits(['accept']);
</script>

<style scoped>
.accept-button :deep(.own-button)
{
  background-color  : yellow !important;
  outline-color     : green !important;
}
.accept-button :deep(.own-button:hover)
{
  background-color: green !important;
}
</style>

Here is the example above.

CodePudding user response:

This is a design limitation of Vue 3 when dealing with multi-root nodes

I wrote about this in my article Scoped styles and multi-root nodes don't work well together.

Understanding the issue

In Vue 3 we can finally have more than "one root node" components. That is great, but there is a design limitation when doing that. Imagine we have a child component:

<template>
  <p >First p</p>
  <p >Second p</p>
</template>

And a parent component:

<template>
    <h1>My awesome component</h1>
    <MyChildComponent />
</template>

<style scoped>
// There is no way to style the p tags of MyChildComponent
.my-p { color: red; }
:deep(.my-p) { color: red; }
</style>

There is no way from the scoped styling of the multi-root parent component to style the child component's p tags.

So in short, a multi-root component, can't target multi-root child component's styles with scoped styles.

Solutions

  • Related