Style Child Components & Dynamic HTML Using Vue 3 Deep Selector

Robin
Updated on March 7, 2024

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.

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.

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 to it.

Also Read: watch VS watchEffect in Vue 3 - Must Know Differences

Related Posts