Vuetify
lastmod 2025-02-14created 2018-07-1263 edits
|
Material Component Framework for Vue.js 2
Categories
Dark theme
- Vuetify — A Material Design Framework for Vue.js # Light and dark
- Application theming — Vuetify.js # Light and Dark
The default is the light theme, and you can change it by adding the dark property.
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify({
theme: { dark: true },
})
Presets
You can add them with the following commands.
- vue add vuetify-preset-basil
- vue add vuetify-preset-crane
- vue add vuetify-preset-fortnightly
- vue add vuetify-preset-owl
- vue add vuetify-preset-rally
- vue add vuetify-preset-reply
- vue add vuetify-preset-shrine
Preparing for TypeScript coding
Apply Vue#Preparing for TypeScript coding first.
Fixing component import errors
- Stackoverflow - Typescript: TS7006: Parameter 'xxx' implicitly has an 'any' type
- How to use vuetify in vue typescript? #112
When importing like this
if you get the following error:
TS7016: Could not find a declaration file for module 'vuetify/lib/components/VForm'. '/home/your/Project/answer-plugin-vms/fe/node_modules/vuetify/lib/components/VForm/index.js' implicitly has an 'any' type. If the 'vuetify' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'vuetify/lib/components/VForm';`
you need to add "noImplicitAny": false to the compiler options in tsconfig.json.
{
"compilerOptions": {
"skipLibCheck": true,
"noImplicitAny": false,
"typeRoots": [
"node_modules/@types",
"node_modules/vuetify/types"
],
"types": ["vuetify"]
}
}
Layouts
Vuetify has two primary layout components: v-app and v-main. The v-app component is the root of your application and directly replaces the default Vue entry point, <div id="app">. The v-main component is a semantic replacement for the main HTML element and the root of your application's content. When Vue mounts to the DOM, any Vuetify component that is part of the layout registers its current height and/or width with the framework core. The v-main component then takes these values and adjusts its container size.
<v-app>
<v-app-bar app></v-app-bar>
<v-main>
<v-container>
Hello World
</v-container>
</v-main>
</v-app>
Centering horizontally and vertically on the screen
<template>
<v-main>
<!-- The card in the center of the screen. -->
<v-container fluid class="fill-height">
<v-row align="center" justify="center">
<v-col class="max-content-width">
<!-- Main Content -->
<v-card>
<!-- ... -->
</v-card>
</v-col>
</v-row>
</v-container>
</v-main>
</template>
<style lang="scss" scoped>
.max-content-width {
max-width: 480px;
}
</style>
The main content is then given a maximum width of 480px.
Customizing item-text
You can use it as an element of item as follows.
According to the manual:
So you can also add it as a lambda, like this.
How to draw an SVG path directly
When you download a package such as @mdi/js, it is drawn using the v-icon component; if you draw the component yourself, do it as follows.
<template>
<svg class="grid-view--table-body-row-drag"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
role="img"
aria-hidden="true"
>
<path :d="icons.dragVertical"></path>
</svg>
</template>
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
import {mdiDragVertical} from '@mdi/js';
@Component
export default class GridView extends Vue {
readonly icons = {
dragVertical: mdiDragVertical
};
}
</script>
<style lang="scss" scoped>
.grid-view--table-body-row-drag {
width: 10px;
height: 32px;
fill: currentColor;
}
</style>
How to add a color accent
As in deep-purple accent-4, put a space after the color name and then give the accent level:
How to apply custom styles that change automatically with the theme
- Stackoverflow - Vuetify - How to set background color
- Stackoverflow - How to override vuetify styles?
Applying styles
You can simply bind the style attribute in the template and set the color directly. This is the worst approach.
<template>
<div class="fill-width" :style="contentStyle"></div>
</template>
<script lang="ts">
import {Vue, Component, Prop, Watch} from 'vue-property-decorator';
@Component
export default class ViewPort extends Vue {
get contentStyle() {
return {'background-color': '#ffffff'};
}
}
</script>
Using Vuetify's colors class
Just import vuetify/lib/util/colors.
<template>
<div class="fill-width" :style="contentStyle"></div>
</template>
<script lang="ts">
import {Vue, Component, Prop, Watch} from 'vue-property-decorator';
import colors from 'vuetify/lib/util/colors'
@Component
export default class ViewPort extends Vue {
get contentStyle() {
if (this.$vuetify.theme.dark) {
return {'background-color': colors.grey.darken1};
} else {
return {'background-color': colors.grey.lighten5};
}
}
}
</script>
Using Vuetify's styles.sass
A component that uses scss to apply the text.secondary color from $material-dark and $material-light as the font color, depending on the theme:
<template>
<p class="text-subtitle-2 font-weight-bold mb-1" :class="textColorClass">
<slot></slot>
</p>
</template>
<script lang="ts">
import {Vue, Component, Prop} from 'vue-property-decorator';
@Component
export default class SubtitleBold extends Vue {
@Prop({type: String})
readonly value!: string;
get textColorClass() {
if (this.$vuetify.theme.dark) {
return 'text-color-dark';
} else {
return 'text-color-light';
}
}
}
</script>
<style lang="scss" scoped>
@import '~vuetify/src/styles/styles.sass';
.text-color-light {
color: map-get(map-get($material-light, 'text'), 'secondary');
}
.text-color-dark {
color: map-get(map-get($material-dark, 'text'), 'secondary');
}
</style>
Using CSS selectors
The v-app documentation of Vuetify says it "propagates the application variant (dark/light) to child components"1. That v-app ends up as the following final HTML:
<div data-app="true" class="v-application v-application--is-ltr theme--dark" id="app">
<!-- ... -->
</div>
And many Vuetify components get their background color propagated through a CSS Selector like the following:
Note that the theme--dark and theme--light classes switch depending on whether Vuetify's dark theme (this.$vuetify.theme.dark) is true or false.
So you can use the class selector above to specify the CSS Selector of child components.
<template>
<div class="grid-view"></div>
</template>
<style lang="scss" scoped>
.grid-view {
}
.theme--light.v-application .grid-view {
background: red;
}
.theme--dark.v-application .grid-view {
background: blue;
}
</style>
This lets you specialize styles for theme changes without using javascript.
Be careful: if you use a Deep Selector like this,
it compiles to the following.
In that case the root element cannot be found, so you must not use a Deep Selector.
For reference, without a Deep Selector it compiles to the following.
Troubleshooting
TypeScript Error: Could not find a declaration file for module 'vuetify/lib’
- Fixing Vuetify Import Errors in typescript - Never test
- When adding typescript - Error: Could not find a declaration file for module 'vuetify/lib’
When applying TypeScript, you may get an error like the one below.
ERROR in C:/workspace/inhasite/general/ctlt_apply/english_clinic/src/plugins/vuetify.ts
2:21 Could not find a declaration file for module 'vuetify/lib'. 'C:/workspace/inhasite/general/ctlt_apply/english_clinic/node_modules/vuetify/lib/index.js' implicitly has an 'any' type.
Try `npm install @types/vuetify` if it exists or add a new declaration (.d.ts) file containing `declare module 'vuetify/lib';`
1 | import Vue from 'vue';
> 2 | import Vuetify from 'vuetify/lib';
| ^
3 | import 'vuetify/src/stylus/app.styl';
4 |
5 | Vue.use(Vuetify, {
Version: typescript 3.2.2, tslint 5.11.0
Add "vuetify" to compilerOptions.types in the tsconfig.json file.
Icon display error
First, add the dependency.
Edit the vuetify.js file as follows.
import Vue from "vue";
import Vuetify from "vuetify/lib";
import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
Vue.use(Vuetify);
export default new Vuetify({
icons: {
iconfont: 'mdi',
},
});
Language change not applied to other components
errorBuckets of v-text-field not updated on language change
See v-text-field.
Using / for division is deprecated
- Stackoverflow - Nuxtjs vuetify throwing lots of
Using / for division is deprecated and will be removed in Dart Sass 2.0.0. - New Sass Deprecation Recommended #13694
: Using / for division is deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($grid-gutter, 3)
More info and automated migrator: https://sass-lang.com/d/slash-div
╷
63 │ 'md': $grid-gutter / 3,
│ ^^^^^^^^^^^^^^^^
╵
node_modules/vuetify/src/styles/settings/_variables.scss 63:11 @import
node_modules/vuetify/src/styles/settings/_index.sass 1:9 @import
node_modules/vuetify/src/styles/styles.sass 2:9 @import
node_modules/vuetify/src/components/VIcon/_variables.scss 1:9 @import
node_modules/vuetify/src/components/VIcon/VIcon.sass 2:9 root stylesheet
Quick fix devDependencies in package.json:
-
"sass": "~1.32.8" -
"sass-loader": "10"
Translation key "dataTable.ariaLabel.****" not found in fallback
If a warning like the one above appears in the browser when using a component such as VDataTable, initialize the Vuetify plugin as follows when creating it:
import Vue from 'vue';
import Vuetify from 'vuetify/lib/framework';
import en from 'vuetify/lib/locale/en';
import ko from 'vuetify/lib/locale/ko';
Vue.use(Vuetify);
export default new Vuetify({
lang: {
locales: {en, ko},
current: 'en',
},
});
To change the language:
This is separate from the language change in vue-i18n, so you have to do each one:
See also
Favorite site
Guide
Reference
- CSS:Example:HideScrollbar
- CSS:flexbox
- Font Awesome
- Material design
- Material Design Icons
- Material UI
- V-calendar
- V-card
- V-col
- V-container
- V-data-table
- V-fab-transition
- V-form
- V-icon
- V-menu
- V-select
- V-text-field
- V-tooltip
- Vue I18n
- Vue Loader
- Vue Test Utils
- Vue.js
- Vue:directives
- Vue:Lifecycle
- Vuetify:Breakpoints
- Vuetify:GridSystem
- Vuetify:Internationalization
- Vuetify:Styles