42
votes

Case 1
We are trying to apply custom a style to a rendered vuetify element:

<template>
    <v-text-field v-model="name" label="Name" />
</template>

<style scoped>
.input-group__input {
    background: red;
}
</style>

But there are no changes.


Case 2
We are trying to style elements rendered by v-html (e.g. external html). For example, we try to apply custom width and height on the img, but it doesn't work:
<template>
    <div v-html="customHTML"></div>
</template>

<script>
export default {
    data: () => ({
        customHTML: `<img src="https://vuetifyjs.com/static/doc-images/carousel/planet.jpg">`;
    })
}
</script>

<style scoped>
img {
    width: 200px;
    height: 200px;
}
</style>

How to apply custom CSS to those elements?

1

1 Answers

115
votes

NOTE: Make sure to include styles as per docs
Also in case of broken components make sure that your app is wrapped inside v-app tag:

<v-app> 
    <v-content>
    //..
    </v-content>
</v-app>

Documentation says:

In order for your application to work properly, you must wrap it in a v-app component.


Solution

use vue-loader's deep selectors >>> like so:

Case 1:

>>>.input-group__input {
    background: red;
}

Case 2:

>>>img {
    width: 200px;
    height: 200px;
}

So there is no need to remove scoped attribute from <style> tag.

Excerpt from docs with regards to pre-processors (for example if you are using <style lang="scss" scoped>):

Some pre-processors, such as Sass, may not be able to parse >>> properly. In those cases you can use the /deep/ combinator instead - it's an alias for >>> and works exactly the same.

Note: deep-selectors were implemented in v12.2.0

Explanation

In both cases CSS changes are not taking effect because elements you are trying to style are not part of your component, and thus don't have data-v-xxxxxxx attribute, which is used for styling elements in the current scope (component) when using <style scoped>.
When using scoped attribute we tell the vue to apply css only to elements with data-v-xxxxxxx, but not nested elements. Thus we need to explicitly use deep-selectors.

For example, in case #1 rendered <v-text-field> will look like so:

// notice `data-v-61b4012e` here:
<div data-v-61b4012e class="input-group input-group--text-field primary--text">
    <label>Name</label>
    <div class="input-group__input"> // and notice no `data-v-61b4012e` here
        <input tabindex="0" aria-label="Name" type="text">
    </div>
    <div class="input-group__details"></div>
</div>

And in case #2 rendered v-html looks like this:

<div data-v-61b4012e> // notice `data-v-61b4012e` here  
    // and no `data-v-61b4012e` on image
    <img src="https://vuetifyjs.com/static/doc-images/carousel/planet.jpg">
</div>

Still not working?

If you are trying to override some style (inline-style) and this solution did not work, you might want to see more about CSS specificity.


Bugs?
It's possible that even if you target properly and use deep-selectors that style is not applied as you would expect. Check if there is coresponding data-v-xxxxxx property on one of the parent elements in rendered html, there might be cases (bugs) when it's not applied, so then there is no way to target it via scoped css. One example was v-menu rendered by v-select, but probably possible to encounter other similar bugs in the future.