8

Summary: I need to style the contents of a <slot>, from the child component. I'm using scoped css and the styles don't apply:

I have the following two components:

<!-- Parent.vue -->
<template>
  <h1>{{ msg }} from Parent</h1>
  <Child>
    <h1>{{ msg }} from Child</h1>
  </Child>
</template>
...
<style scoped>
h1 {
  color: green;
}
</style>

<!-- Child.vue -->
<template>
  <slot></slot>
</template>
...
<style scoped>
h1 {
  color: red;
}
</style>

I want the 2nd <h1> to be red, but it's green, since the component is rendered with something like:

<h1 data-v-452d6c4c data-v-2dcc19c8-s>Hello from Child</h1>

<style>
h1[data-v-452d6c4c] {
  color: green;
}
h1[data-v-2dcc19c8] {
  color: red;
}
</style>

data-v-452d6c4c comes from Parent, and data-v-2dcc19c8-s from Child

If the second attribute, in the <h1> tag, was just data-v-2dcc19c8 the style I wanted would be applied, but since it has that -s suffix (slot?), it doesn't.

I could probably find some other solution with a class or something, but I rarely use <slot> and I want to understand the inner workings. That -s tells me that what I'm trying to do can be dealt with the help of the framework, what am I missing?

A working sample:

https://codesandbox.io/s/condescending-brown-ilfwn

Dan
  • 59,490
  • 13
  • 101
  • 110
lalibi
  • 3,057
  • 3
  • 33
  • 41

1 Answers1

20

Use the new :slotted selector in Vue 3:

Child.vue

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

<script>
export default {
  name: "Child",
};
</script>

<style scoped>
:slotted(h1) {
  color: red !important;
}
</style>

In Vue 3, child scoped styles don't affect slotted content by default.

In your particular example, the !important modifier is also necessary because the parent also defined an h1 style which would take precedence otherwise

Dan
  • 59,490
  • 13
  • 101
  • 110
  • 1
    Thank you for this answer, I have been looking for a way to do slotted styling in Vue for quite a while – Marcos de Andrade Jul 27 '21 at 14:54
  • Is there a page in the docs about this? Searching the docs for `v-slotted` doesn't show any results – Mike Harrison Jan 10 '22 at 00:26
  • 2
    @MikeHarrison - It's [here](https://v3.vuejs.org/api/sfc-style.html#slotted-selectors) and actually the syntax has changed again. Now you use `:slotted(h1)` instead of `::v-slotted(h1)`. The answer has been changed to reflect this. (Reposted comment to fix link.) – Dan Jan 22 '22 at 04:40