I have a VDialog containing a VCard which in turn contains a VSelect. When I open the VSelect, it is hard to see the drop-down list of options as it has the same color as the VCard. Both seem to have background: rgb(var(--v-theme-surface));
The only thing making the dropdown stand out is a shadow, but in a dark-theme, you can barely see it.
What is the recommended way to change the background of a VSelect (or VMenu, VCombobox) if it is inside a VDialog or VCard?
I know Vuetify 3 has a way to change global config (including nested options, like a VSelect inside a VCard) but I could not get that to work.
I also tried with CSS variables, changing the value of the --v-theme-surface
CSS property, but it looks like the dropdown is moved outside of the parent container and put close to the html <body>
, so I can't target it.
Is there a way to 'send in' a CSS class into the child drop down menu so I can target it that way?
Many thanks.
I am not aware of a way to change styles of nested components through Vuetify directly, but using the :menu-props
property, you can pass a configuration object to the underlying v-menu
component. The content of the :content-class
property will be set as class on the overlay content node:
<v-select
...
:menu-props="{
contentClass: 'lighter-surface',
}"
>
With this, you can now define a CSS rule to adjust the background color variable:
.lighter-surface > .v-theme--dark{
--v-theme-surface: var(--v-theme-on-surface-variant); /* or something like 55,55,55; */
}
const { createApp } = Vue;
const { createVuetify } = Vuetify
const vuetify = createVuetify({theme: {defaultTheme: 'dark'}})
const app = {}
createApp(app).use(vuetify).mount('#app')
.lighter-surface > .v-theme--dark{
--v-theme-surface: var(--v-theme-on-surface-variant);
}
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" />
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-card class="ma-4">
<v-card-title>Selection Card</v-card-title>
<v-card-text>
<v-select
:items="['option 1', 'option 2', 'option 3']"
label="Select"
:menu-props="{
contentClass: 'lighter-surface',
}"
></v-select>
<div style="height: 200px;">
</div>
</v-card-text>
</v-card>
</v-main>
</v-app>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
If you don't want to change global styles, you can try to attach the v-menu
to the v-card
, using the :attach
property, then you could work with local styles. Not sure if it's worth it though.
Or you can solve it by adding your own theme:
const vuetify = createVuetify({
theme: {
defaultTheme: 'dark',
themes: {
darkOnSurface: { // <--- name of the theme
dark: true, // <--- extend dark theme
colors: {
surface: 'blue', // <--- override color variant from dark theme
}
}
}
}
})
And then set that theme in the v-menu
:
<v-select
...
:menu-props="{
theme: 'darkOnSurface',
}"
></v-select>
The advantage is that you can use it on all Vuetify components.
const {
createApp
} = Vue;
const {
createVuetify
} = Vuetify
const vuetify = createVuetify({
theme: {
defaultTheme: 'dark',
themes: {
darkOnSurface: {
dark: true,
colors: {
surface: 'blue',
}
}
}
}
})
const app = {}
createApp(app).use(vuetify).mount('#app')
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" />
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-card class="ma-4">
<v-card-title>Selection Card</v-card-title>
<v-card-text>
<v-select
:items="['option 1', 'option 2', 'option 3']"
label="Select"
:menu-props="{
theme: 'darkOnSurface',
}"
></v-select>
<div style="height: 200px;">
</div>
</v-card-text>
</v-card>
</v-main>
</v-app>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>