We use Vue 3 deep selector when we want to add CSS styles to the child components from a parent, even if they are nested multiple levels deep. We can apply the same technique for styling the dynamically rendered HTML using v-html
directive.
In order to add CSS styles to elements from child components or dynamically rendered HTML use the deep selector :deep()
pseudo-class in Vue 3. This pseudo-class accepts any type of CSS selector like class, id, or element, and passes the style to that selected element.
In this post, we will understand everything about Vue 3 deep selector, how it works and how you can use it to style deeply nested elements in child components and dynamic HTML.
Understanding Vue 3 :deep() Selector
If you use scoped styles in your Vue single-file component, those styles will apply only to the HTML elements defined in that particular component.
Sometimes you might want to pass the style to your child component from the parent. But if you select and add style to an element that is defined in child components then it will not work.
In order to solve this problem, Vuejs provides a pseudo-class that you can use inside your scoped style. You can use any CSS selector to select an element.
<style scoped>
/* Using tag selector */
:deep(div) {
/* ... */
}
/* Using class selector */
:deep(#title) {
/* ... */
}
/* Using id selector */
.content :deep(.title) {
/* ... */
}
</style>
As you can see, I am using an HTML tag, class, and id to select an element in the <style>
section. You can also select elements present inside a specific element.
In this example, I am selecting every element that has a class title
inside a specific HTML element that contains the class content
. That's how this deep selector works in Vue 3.
Also Read: How to Use Vue 3 CSS Variables With v-bind: Reactive Styles
Styling Child Components Through The Parent
I have a Parent.vue
component in my project and I am using Child.vue
component in it as a child. The Child.vue
component has a div
element that I want to style from my Parent.vue
component.
Parent.vue Component:
<template>
<div class="content">
<Child />
</div>
</template>
<script setup>
import Child from './Child.vue'
</script>
<style scoped>
/* Add style here */
</style>
Child.vue Component:
<template>
<div>
<div class="title">Child Component</div>
<Products />
</div>
</template>
<script setup>
import Products from './Products.vue'
</script>
I am also using another component as a child inside the Child.vue
component. Now if I try to select the class title
and add CSS style to this element from my Parent.vue
component, it won't work.
In this situation, I have to use the deep selector syntax. This is the syntax you need to use:
/* Parent.vue component */
<style scoped>
.content :deep(.title) {
font-size: 25px;
color: #0679b6;
}
.content :deep(.name) {
color: #033c7a;
}
</style>
Here I am adding styles to every .title
present inside the .content
element where I am using my child component. You can also use this to style the nested child components.
In this case, I am selecting all the .name
class from the Products.vue
component which is a child of the Child.vue
component. Now spin up your application and see the result in your browser.
You will find that styles are being added to those HTML elements. That's how you can pass CSS styles from parent to child components in Vue 3.
Also Read: How to Pass Data From Child to Parent in Vue 3 (Composition API)
Styling Dynamic HTML Using Deep Selector
This Vue 3 deep selector can be used for the dynamically rendered HTML elements. Sometimes we fetch HTML content from an API and render it on our page at runtime.
You can't add CSS styles in your component's scoped <style>
section for such content. Vue's template compiler can't process those dynamic HTML. That's why you need to use the deep selector to add style to those HTML elements.
<!-- SinglePost.vue Component -->
<template>
<div>
<main v-html="html"></main>
</div>
</template>
<script setup>
import { ref } from 'vue'
const html = ref('<div class="post">This is dynamic content</div>')
</script>
<style scoped>
main :deep(.post) {
font-size: 16px;
color: #2c2c2d;
}
</style>
In this SinglePost.vue
component, I am storing some HTML content and displaying them as HTML using v-html
directive. In your case, you can also fetch this content from an API.
This dynamic HTML content has a div
element with a class post
that I want to select in my component. As I said before, you can't select this class directly in your scoped styles.
That's why I am selecting the .post
class present inside the main
tag using the :deep()
pseudo-class. Now I can add any CSS property I want to this element.
Also Read: watch VS watchEffect in Vue 3 - Must Know Differences
Conclusion
Vue 3 has amazing support for CSS styles already. This deep selection feature gives us more control over our page layout and its styles. It is a powerful tool that offers a range of possibilities.
The deep selector enables you to apply styles to nested elements within a component, making it easier to maintain consistency and reuse styles. Use :deep()
pseudo-class for styling elements from child components and dynamically generated HTML in Vue 3.