vuetify Documentation

TypeScript javascript & material repository by @vuetifyjs. Model Context Protocol (MCP) server & tools with 41k stars.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy vuetify on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name vuetify -p 8095:8095 --restart always caddy:alpine
Configured Services & Ports
โš™๏ธ docs
image: caddy:alpine
๐Ÿ”Œ Ports: ${PORT:-8095}:80
docker-compose.yml
yaml (docker-compose.yml)
services:
  docs:
    image: caddy:alpine
    ports:
      - ${PORT:-8095}:80
    volumes:
      - ./packages/docs/dist:/srv
      - ./packages/docs/build/Caddyfile:/etc/caddy/Caddyfile

File: README.md

๐Ÿ–ฅ๏ธ Documentation

To check out the documentation, visit vuetifyjs.com.

โšก Quick Start

Getting started with Vuetify is easy. To create a new project, choose your package manager and run one of the following commands:

Using pnpm

bash
pnpm create vuetify

Using yarn

bash
yarn create vuetify

Using npm

bash
npm create vuetify@latest

Using bun

bash
bun create vuetify

For more information on how to get started, such as using Nuxt or Laravel, check out the official Installation guide.

๐Ÿ’– Supporting Vuetify

Vuetify is a MIT licensed project that is developed and maintained by the Core Team. Sponsor Vuetify and receive some awesome perks and support Open Source Software at the same time! ๐ŸŽ‰

  • [Become a backer or sponsor on GitHub](https://github.com/users/johnleider/sponsorship)
  • [Become a backer or sponsor on Open Collective](https://opencollective.com/vuetify) **(supports the Core team)**
  • [Become a subscriber on Tidelift](https://tidelift.com/subscription/request-a-demo?utm_source=npm-vuetify&utm_medium=referral&utm_campaign=enterprise)
  • [Make a one-time payment with Paypal](https://paypal.me/vuetify)
  • What's the difference between GitHub Sponsors and OpenCollective?

    Funds donated through GitHub Sponsors directly support John Leider and the ongoing development and maintenance of Vuetify. Funds donated via Open Collective are managed with transparent expenses and will be used for compensating work and expenses for Core team members. Your name/logo will receive proper recognition and exposure by donating on either platform.

    **Special Sponsor**

    **Diamond Sponsors**

    **Platinum Sponsors**


    ๐Ÿš€ Introduction

    Vuetify is a no design skills required UI Library with beautifully handcrafted Vue Components. No design skills required โ€” everything you need to create amazing applications is at your fingertips. Vuetify has a massive API that supports any use-case. Some highlights include:

    • Customizable: Extensive customization options with SASS/SCSS and Default configuration and Blueprints
    • Responsive Layout: The default configuration of Vuetify components is responsive, allowing your application to adapt to different screen sizes.
    • Theme System: A powerful color system that makes it easy to style your application with a consistent color palette.
    • Vite Support: Smaller bundle sizes with automatic tree-shaking
    • min. 6 months Long-term support for Major releases
    • Internationalization: 42+ supported languages

    Browser Support

    Vuetify supports all modern browsers, including Safari 13+ (using polyfills). Components are designed for a minimum width of 320px.

    ๐ŸŒŽ Vuetify Ecosystem

    Resources

    Name Description
    ๐Ÿ•ถ๏ธ Vuetify Awesome Awesome stuff built with Vuetify.
    ๐Ÿ—‘๏ธ Vuetify Bin A pastebin for saving code snippets.
    ๐Ÿซง Vuetify Create Scaffolding tools for creating new Vuetify projects.
    ๐Ÿ’ญ Vuetify Discord Our massive and inclusive Discord server where you can ask questions, share feedback, and connect with other Vuetify developers.
    ๐Ÿงน Vuetify ESLint An opinionated ESLint config for styling and an ESLint plugin for upgrading Vuetify version.
    ๐Ÿ› Vuetify Issues A web application for reporting bugs and issues with Vuetify, Documentation, or one of our other packages.
    ๐Ÿ“ฆ Vuetify Loader A monorepo of compiler plugins for autoloading Vuetify components and configuring styles.
    ๐Ÿง  Vuetify MCP A Model Context Protocol server for developing with Vuetify and Agents.
    ๐ŸŽฎ Vuetify Playground A Vuetify 3 playground built using vuejs/repl where you can play with our components.
    โœ‚๏ธ Vuetify Snips Pre-built code snippets for Vuetify components that you can use in your projects
    ๐Ÿ›’ Vuetify Store The official Vuetify Store where you can download free digital products, purchase pre-made themes, and more.

    ๐Ÿ™‹โ€โ™‚๏ธ Questions

    For help and support questions, please use our Discord community. This issue list of this repo is exclusively for bug reports and feature requests.

    ๐Ÿ› Issues

    Use our Issue generator to report bugs and request new features.

    Please make sure to read the Important Information before opening an issue. Issues not confirming to the guidelines may be closed immediately.

    2๏ธโƒฃ Vuetify 2 Support
    Vuetify 2 is now End Of Life (EOL) and is no longer supported, even for security issues. Commercial support for this version is available from our partner, HeroDevs.

    ๐Ÿ“ Changelog

    Detailed changes for each release are documented in the release notes.

    ๐Ÿ’โ€โ™‚๏ธ Contributing

    Developers interested in contributing should read the Code of Conduct and the Contribution Guide.

    Please do not ask general questions in an issue. Issues are only to report bugs, suggest
    enhancements, or request new features. For general questions and discussions, ask in the community chat.

    To help you get you familiar with our contribution process, we have a list of good first issues that contain bugs which have a relatively limited scope. This is a great place to get started. If you have any questions, please join us on the community chat.

    We also have a list of help wanted issues that you might want to check.

    ๐Ÿ“‘ License

    Vuetify is available under the MIT software license.

    Copyright (c) 2016-present Vuetify, LLC


    This project exists thanks to all the people who contribute ๐Ÿ˜!


    File: packages/docs/src/pages/en/getting-started/browser-support.md


    meta:
    title: Browser support
    keywords: vuetify browser support
    related:

    • /getting-started/installation/
    • /introduction/why-vuetify/
    • /features/sass-variables/

    Browser support

    Vuetify 4 is a next generation framework that takes advantage of the latest web technology features and requires an evergreen browser to function.

    Browsers

    This is not an exhaustive list of compatible browsers, but the main targeted ones. If you are using a browser that is not listed here, it is not officially supported.

    Browser Version Status
    Chromium (Chrome, Edge) 119 โœ… Supported *
    ^^ 99 โš ๏ธ Partial support **
    Firefox 128 โœ… Supported *
    ^^ 97 โš ๏ธ Partial support **
    Safari 16.4 โœ… Supported
    Internet Explorer โ›” Not supported
    Other Browsers โ“ Not officially supported
    • All browsers on iOS use WebKit and have the same support as Safari
      ** Some components may have incorrect colors due to lack of support for relative color syntax (e.g. rgb(from ...)). VNumberInput locale-aware grouping requires Intl.NumberFormat with string useGrouping options (Chrome 106+, Firefox 115+).

    This table is updated with minor releases of Vuetify. Chrome, Firefox, and Safari will be supported at least two years back from the Vuetify x.x.0 release date.
    Current start date is December 2023.

    Support for older browsers may be possible with additional polyfills and PostCSS plugins, but has not been tested and is not guaranteed. If you need to support older browsers we recommend using Vuetify 2 or 3.


    File: packages/docs/src/pages/en/getting-started/contributing.md


    meta:
    title: Contributing
    keywords: contribute, contributing, feature request
    related:

    • /getting-started/unit-testing/
    • /about/code-of-conduct/
    • /introduction/roadmap/

    Contributing

    Vuetify is made possible by an amazing community that submits issues, creates pull requests, and provides invaluable feedback.

    It is our job to enable you to create amazing applications. A lot of the time, you come across something that can be made better. Maybe you find a bug, or you have an idea for additional functionality. That's great! It's as easy as cloning the Vuetify repository to get started working in a development environment.

    Reporting Issues

    The issue list of this repo is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately. Before reporting an issue:

    • Search for similar issues, it may have been answered already.

      If a similar issue already exists, you do not need to open another issue for this, if you want to help with it in any way, you can help by giving appropriate information in the already existing issue.

    • Try to reproduce with the latest version in Vuetify Play or a repository that can be cloned to produce the expected behavior.
    • Make sure that the reproduction is MINIMAL and CONCISE

    These steps ensure that we have all the information necessary to quickly triage and resolve your issue. Once your reproduction is complete, submit a new issue using the Vuetify Issue Creator. Using this issue creator is required, otherwise the issue will be closed automatically.

    When writing an issue please provide as much detail as possible. Note that "reproduction steps" should be a series of actions another developer should take after clicking your reproduction link, not a recollection of how you discovered the bug.

    Issues that are convoluted and lacking a proper reproduction may be closed by a member of the Core Team. For additional questions regarding reporting issues and creating reproductions, join the official Vuetify Discord community.

    ::: tip
    When you create a reproduction, exclude all elements, properties, and data variables that are not needed for the reproduction. This helps drastically reduce the time it takes to triage the issue and ultimately resolve it.
    :::

    In the next section you will learn step-by-step how to set up your local environment and how to configure Vuetify for development.

    Local development

    The Vuetify repository is a lerna monorepo that connects the vuetify library, docs, api generator, and reduces the friction of working with multiple projects at once. The following guide is designed to get you up and running in no time.

    Setting up your environment

    We recommend using FNM (with all four options enabled) to automatically set up and use the exect node and pnpm versions specified in package.json.

    Required software:

    Some of our dependencies use node-gyp to build themselves. You don't need to install node-gyp itself but may require additional tools, especially on windows. See the node-gyp documentation for more details.

    Once you have everything installed, clone the repository:

    bash
    # Using HTTPS
    git clone https://github.com/vuetifyjs/vuetify.git
    
    # Using SSH
    git clone [email protected]:vuetifyjs/vuetify.git

    ::: info
    Which remote URL should I use?
    :::

    Then install dependencies and perform an initial build to link all the packages together:

    bash
    # Navigate to the vuetify folder
    cd vuetify
    
    # Install all project dependencies
    pnpm i
    
    # Build the packages
    pnpm build vuetify
    pnpm build api

    The build process compiles all the Vuetify packages for development and may take a while (grab some โ˜•). Once the packages are built, you can start developing.

    Vuetify

    The Vuetify library is located in packages/vuetify. In packages/vuetify/dev you will find a Playground.vue file; running pnpm dev from the project root will start a dev server on localhost:8090 with this file loaded. Test your changes in the Playground.vue file you copied, then paste its contents into your pull request when you're ready.

    You can also test Vuetify in your own project using pnpm link:

    • Navigate to packages/vuetify
    • Run pnpm link --global
    • Navigate to your project's directory
    • Run pnpm link --global vuetify
    • Clear Vite's cache by deleting node_modules/.vite folder

    If your project is using vuetify-loader you will have to run pnpm build:lib in the vuetify package to see changes, otherwise you can use pnpm watch for incremental builds.

    Playground.vue

    The Playground file is a cleanroom used for Vuetify development and is the recommended way to iterate on changes within the framework.

    html
    <template>
      <v-app>
        <v-container>
          
        </v-container>
      </v-app>
    </template>
    
    <script setup>
      //
    </script>

    Automated testing

    Vuetify uses Vitest for unit tests, Vitest browser mode with Playwright for component interaction tests, and Vizzly for visual regression tests.

    • pnpm test - run all tests
    • pnpm test:unit - run only unit tests
    • pnpm test:browser - run only browser tests
    • pnpm test:open - run browser tests in a chrome window
      • use this if you need devtools to debug a failing test
    • pnpm test:screen - run only screenshot tests, saves a report to http://localhost:47392/
    • pnpm tdd - start the vizzly dev server, follow with test, test:screen, test:browser, or test:open to actually run tests. Screenshot baselines and diffs can be managed and viewed at http://localhost:47392/
      • run pnpm tdd:stop when you're done to kill the background process

    The test:* commands all accept a list of test names to filter by, eg. pnpm test textfield textarea to only run VTextField and VTextarea tests.

    Visual regression workflow

    • Checkout the base branch (master or dev)
    • Run pnpm tdd
    • Visit http://localhost:47392/stats and click "Reset baselines"
    • Run pnpm test:screen
    • Click "Accept all changes"
    • Checkout your PR branch
    • Run pnpm test:screen again
    • Any visual differences will be shown on http://localhost:47392

    Documentation

    The documentation is located in packages/docs but also uses some files from packages/api-generator. A dev server for the documentation can be started by running pnpm dev docs from the project root and will be available on localhost:8095 by default.

    If you want to see changes from Vuetify in the documentation you need to run pnpm build:lib in the vuetify package before starting the documentation server.

    API Generator

    All api descriptions are managed via the api-generator package. This package must be built prior to running or building the docs. Descriptions can be updated via the JSON files located in the src/locale/en folder. Some general guidelines to follow when handling api descriptions are:

    • en language only. Translations are handled via Crowdin.
    • Prop names should be formatted using bold markdown eg: prop-name.
    • Slot and other code related text should be formatted using code markdown eg: some-slot.
    • Description keys should be in camelCase, except for slot keys which should be kebab-case.
    • Put keys in alphabetical order.
    • Descriptions utilize a hierarchy of generic.json < Source.json < Component.json to reduce duplication. Source can be viewed using the Developer Mode in docs settings.

    Adding API Documentation

    When creating a new component (or composable, though this is typically done by the Vuetify team), you need to add a corresponding JSON file named ComponentName.json in packages/api-generator/src/locale/en/. This file should contain descriptions for props, slots, events, and exposed methods. After adding or updating JSON files, run pnpm build api to regenerate the dist language files. Keep in mind:

    • Changes to Vuetify require a rebuild before building the API
    • The API must be built before running the documentation server

    Enabling developer mode in the documentation settings will allow you to see the source of truth on API description pages.

    Submitting Changes / Pull Requests

    First you should create a fork of the vuetify repository to push your changes to. Information on forking repositories can be found in the GitHub documentation.

    Then add your fork as a remote in git:

    bash
    # Using HTTPS
    git remote add fork https://github.com/YOUR_USERNAME/vuetify.git
    
    # Using SSH
    git remote add fork [email protected]:YOUR_USERNAME/vuetify.git

    Choosing a base branch

    Before starting development you should know which branch to base your changes on. If in doubt use master as changes to master can usually be merged into a different branch without rebasing.

    Version Type of change Branch
    Vuetify 4 Documentation master
    Vuetify 4 Bug fixes master
    Vuetify 4 New features dev
    Vuetify 5 Features with breaking changes next
    Vuetify 3 Documentation v3-stable
    Vuetify 3 Bug fixes v3-stable
    Vuetify 2 Documentation v2-stable
    bash
    # Switch to the desired branch
    # v4
    git switch master
    # v3
    git switch v3-stable
    
    # Pull down any upstream changes
    git pull
    
    # Create a new branch to work on
    git switch --create fix/1234-some-issue

    ::: warning
    Never commit directly to the base branches, always create a feature branch to work on
    :::

    Commit your changes following our guidelines, then push the branch to your fork with git push -u fork and open a pull request on the Vuetify repository following the provided template.

    ::: error
    Pull requests that include unrelated commits or your local merges will be CLOSED without notice
    :::

    Working with GitHub

    Vuetify's repository lives on GitHub and is the primary location for all development related information.

    Some of the more notable links within these services include:

    GitHub


    The following sections are designed to familiarize you with our standard operating procedures for Vuetify development.

    Issue triage

    With the size and popularity of Vuetify has come a constant influx of new issues, questions, and feature requests. To organize these requests the Core Team developed tools to aid not only the triaging of issues, but creating them as well.

    The Issues board makes heavy use of GitHub's label system with some light automation, such as adding the triage label to new issues.

    For Docs - Language

    We do not accept PRs for any documentation changes pertaining to languages other than en. All changes for languages other than en are to be submitted through our Crowdin project. You can help translate in one of 2 ways:

    • Using in-context translation service directly through the documentation site. To get started simply select Help Translate in the language drop down in the docs.
    • Directly through the Crowdin project.

    Note: Languages will not be added to the language drop down on the docs site until they have at least 50% of their translations completed.

    Requesting new features

    Pending

    Commit guidelines

    All commit messages are required to follow the conventional-changelog standard using the angular preset. This standard format consists of 2 types of commits:

    • With scope: <type>(scope): <subject>

      bash
      fix(VSelect): don't close when a detachable child is clicked
      
      fixes #12354
    • Without scope: <type>: <subject>

      bash
      docs: restructure nav components
      
      Moved duplicated functionality in drawer to reduce
      scope of responsibility

    General Rules

    • Commit messages must have a subject line and may have body copy. These must be separated by a blank line.

    • The subject line must not exceed 60 characters

    • The subject line must be written in imperative mood (fix, not fixed / fixes etc.)

    • The body copy must include a reference all issues resolved:

      bash
      docs(sass-variables): fix broken link to api
      
      resolves #3219
      resolves #3254
    • The body copy must be wrapped at 72 characters

    • The body copy must only contain explanations as to what and why, never how. The latter belongs in documentation and implementation.

    Commit types

    The following is a list of commit types used in the angular preset:

    • feat: Commits that result in new features or functionalities. Backwards compatible features will release with the next MINOR whereas breaking changes will be in the next MAJOR. The body of a commit with breaking changes must begin with BREAKING CHANGE, followed by a description of how the API has changed.
    • fix: Commits that provide fixes for bugs within vuetify's codebase.
    • docs: Commits that provide updates to the docs.
    • style: Commits that do not affect how the code runs, these are simply changes to formatting.
    • refactor: Commits that neither fixes a bug nor adds a feature.
    • perf: Commits that improve performance.
    • test: Commits that add missing or correct existing tests.
    • chore: Other commits that don't modify src or test files.
    • revert: Commits that revert previous commits.

    File: packages/docs/src/pages/en/getting-started/frequently-asked-questions.md


    meta:
    title: Frequently asked questions
    keywords: frequently asked questions, faq
    related:

    • /introduction/why-vuetify/
    • /getting-started/contributing/
    • /getting-started/installation/

    Frequently asked questions

    Stuck on a particular problem? Check some of these common gotchas before creating a ticket. If you still cannot find what you are looking for, you can submit an issue on GitHub or ask in our community.

    Questions

    The following responses are a collection of common questions asked by the Vuetify community.

    • What is Vuetify? { #what-is-vuetify }

      Vuetify is a Vue.js framework that helps to create beautiful and responsive user interfaces. It includes a wide variety of customizable and reusable components for building modern applications.

    • Does Vuetify provide support? { #does-vuetify-provide-support }

      Vuetify is a free to use Open Source project released under the MIT license. There are multiple ways to receive support for Vuetify:

    • What is the difference between Vuetify and Vue? { #what-is-the-difference-between-vuetify-and-vue }

      Vuetify is a framework that is built on top of Vue.js. It is a collection of components that can be used to build applications. Vue.js is a JavaScript framework that is used to build user interfaces.

    • What versions of Vue.js are compatible with Vuetify? { #what-versions-of-vuejs-are-compatible-with-vuetify }

      Vuetify is compatible with Vue.js 3.0.0 and above.

    • Is Vuetify 2 still supported? { #is-vuetify-2-still-supported }

      Vuetify 2 reached End of Life (EOL) on January 25th, 2025. For security and commercial support, see our partner, HeroDevs.

    • Can I use Vuetify with other CSS frameworks? { #can-i-use-vuetify-with-other-css-frameworks }

      Yes, you can use Vuetify with other CSS frameworks, but it is typically not recommended. If you are integrating Vuetify into an existing application that is using another CSS framework, you may want to disable the default color and utility generation. See the SASS Variables page for more information.

    • Can I customize the styling of Vuetify components? { #can-i-customize-the-styling-of-vuetify-components}

      Yes, you can customize the styling of Vuetify components using the Global configuration. Vuetify also provides SASS variables that can be overridden to change the look and feel of the components.

    • Where can I get help with Vuetify? { #where-can-i-get-help-with-vuetify }

      If you need help with an issue, please use one of our help channels:

    • Can I contribute to Vuetify? { #can-i-contribute-to-vuetify }

      Yes, we welcome all contributions. Please see our contributing guide for more information.

    • Can I use Vuetify with server-side rendering? { #can-i-use-vuetify-with-server-side-rendering }

      Yes, Vuetify supports server-side rendering. Set the ssr property to true in your vuetify configuration object.

      js { resource="src/plugins/vuetify.js" }
      import { createVuetify } from 'vuetify'
      
      export default createVuetify({
        ssr: true,
      })
    • Is there support for Nuxt 3? { #is-there-support-for-nuxt-3 }

      Yes, Vuetify 3 is compatible with Nuxt 3 but does not currently have a community Nuxt module.

    • What is Vuetify Labs? { #what-is-vuetify-labs }

      Vuetify Labs is a collection of components that are still in development. They are not considered stable and may change at any time. They are not included in the default Vuetify installation and must be imported individually. See the Labs page for more information.

    • Does Vuetify have Nightly Builds? { #does-vuetify-have-nightly-builds }

      Yes, Vuetify has nightly builds. See the Nightly Builds page for more information.

    • I found a bug, what should I do? { #i-found-a-bug-what-should-i-do }

      Please create a new issue with our Issue Generator. Please make sure to check for existing issues before creating a new one.

    • Why did Vuetify 3 change value to model-value?

      The value prop was changed in Vue 3 to support a new v-model syntax. See the official Vue docs for more information on Component v-model.

    • Is Vuetify 3 compatible with @vue/compat?

      Not directly, you have to set configureCompat({ MODE: 3 }) globally and MODE: 2 in each of your components that you want to run in compatibility mode. There will still be some incorrect warnings that can be ignored with the -ATTR_FALSE_VALUE filter in devtools.


    File: packages/docs/src/pages/en/getting-started/release-notes.md


    fluid: true
    meta:
    title: Release notes
    keywords: migration, releases, upgrading vuetify
    related:

    • /introduction/long-term-support/
    • /getting-started/contributing/
    • /introduction/roadmap/

    Release notes

    The Vuetify team performs releases on a weekly basis.


    File: packages/docs/src/pages/en/getting-started/unit-testing.md


    meta:
    title: Unit testing
    keywords: unit testing vuetify, testing vuetify, vuetify spec tests
    related:

    • /getting-started/frequently-asked-questions/
    • /getting-started/contributing/
    • /components/text-fields/

    Unit Testing

    Add regression protection by adding unit tests to your Vuetify application

    Usage

    Unit tests are an important (and sometimes ignored) part of developing applications. They help us secure our processes and workflows, ensuring that the most critical parts of our projects are protected from accidental mistakes or oversights in our development.

    Because of this, Vue has its own testing utility called vue-test-utils. It provides useful features for interacting with Vue components and works with many popular test runners.

    Using Vite

    Vite is a fast, opinionated frontend build tool that serves your code via native ES Module imports during dev and bundles it with Rollup for production. It provides a great developer experience and is the recommended build tool for Vuetify applications.

    First, update your vite.config.js file to inline the vuetify dependency:

    js { resource="vite.config.js" }
    import { defineConfig } from 'vite'
    
    export default defineConfig({
      test: {
        globals: true,
        environment: 'jsdom',
        server: {
          deps: {
            inline: ['vuetify'],
          },
        },
      },
    })

    Setup Vitest

    Vitest is a popular test runner that provides a great developer experience. It is fast, easy to use, and provides useful features like snapshot testing. To get started, install the following dependencies:

    ::: tabs

    bash [pnpm]
    pnpm add @vue/test-utils vitest resize-observer-polyfill --save-dev
    bash [yarn]
    yarn add @vue/test-utils vitest resize-observer-polyfill --dev
    bash [npm]
    npm install @vue/test-utils vitest resize-observer-polyfill --save-dev
    bash [bun]
    bun add @vue/test-utils vitest resize-observer-polyfill --dev

    :::

    Once installed, create a new folder at the root of your application named tests/spec and add a new file named HelloWorld.spec.js. The following example shows how to setup a basic unit test for a Vuetify component:

    js { resource="tests/spec/helloworld.spec.js" }
    import { mount } from '@vue/test-utils'
    import { expect, test } from 'vitest'
    import { createVuetify } from 'vuetify'
    import * as components from 'vuetify/components'
    import * as directives from 'vuetify/directives'
    import HelloWorld from '../../src/components/HelloWorld.vue'
    
    const vuetify = createVuetify({
      components,
      directives,
    })
    
    global.ResizeObserver = require('resize-observer-polyfill')
    
    test('displays message', () => {
      const wrapper = mount({
        template: '<v-layout><hello-world></hello-world></v-layout>'
      }, {
        props: {},
        global: {
          components: {
            HelloWorld,
          },
          plugins: [vuetify],
        }
      })
    
      // Assert the rendered text of the component
      expect(wrapper.text()).toContain('Components')
    })

    Testing Vuetify Components

    When testing Vuetify components, we recommend running tests in a real browser environment instead of jsdom.

    • Vitest (browser mode) โ€“ Fast, Vite-native test runner with browser support.
    • Playwright โ€“ End-to-end testing in actual browsers.
    • Cypress โ€“ Great for integration and E2E tests.

    Rendering with Vuetify

    To properly render Vuetify components in tests, create a Vuetify instance and pass it to the test renderer. You donโ€™t need to mock transitions or other internals.

    ts { resource="vuetify/packages/vuetify/test/index.ts" }
    export function render<C> (
      component: C,
      options?: RenderOptions<C> | null,
      vuetifyOptions?: VuetifyOptions
    ): RenderResult {
      const vuetify = createVuetify(mergeDeep({ icons: { aliases } }, vuetifyOptions))
    
      const defaultOptions = {
        global: {
          stubs: {
            transition: false,
            'transition-group': false,
          },
          plugins: [vuetify],
        },
      }
    
      const mountOptions = mergeDeep(defaultOptions, options!, (a, b) => a.concat(b))
    
      return _render(component, mountOptions)
    }

    Using `data-testid`

    For reliable queries in tests, use data-testid attributes in your components:

    html
    <v-btn data-testid="submit-btn">Submit</v-btn>
    ts
    const { getByTestId } = render(MyComponent)
    expect(getByTestId('submit-btn')).toBeInTheDocument()

    Accessibility Considerations

    Tests should respect user accessibility preferences. Configure prefers-reduced-motion when testing animations to avoid flakiness and ensure accessibility compliance.


    File: packages/docs/src/pages/en/getting-started/upgrade-guide.md


    meta:
    nav: Upgrade guide
    title: Upgrade guide
    keywords: migration, upgrade, releases, upgrading vuetify, alpha, v4
    related:

    • /introduction/roadmap/
    • /introduction/long-term-support/
    • /introduction/enterprise-support/

    Upgrade Guide

    This page contains a detailed list of breaking changes and the steps required to upgrade your application to Vuetify 4

    Quick Start with Vuetify MCP

    The fastest way to check your project for breaking changes is with Vuetify MCP. To get started, run the following in your terminal:

    bash
    # Claude Code
    claude mcp add --transport http vuetify-mcp https://mcp.vuetifyjs.com/mcp
    
    # Configure for hosted remote server
    npx -y @vuetify/mcp config --remote
    
    # Or configure for local installation
    npx -y @vuetify/mcp config

    Once the MCP server is set up and loaded you will gain access to new tools such as:

    • get_upgrade_guide: Get a list of all breaking changes in the upgrade guide.
    • get_v4_breaking_changes: Get a list of all breaking changes in Vuetify 4.

    Now, prompt your agent with the following:

    text
    Using the vuetify-mcp server, scan this project for Vuetify 3 to 4 breaking changes. List each issue found with the file, line number, and recommended fix.

    This will automatically analyze your codebase and provide a tailored list of changes you need to make.

    If you have any questions about the upgrade process, come visit us at community.vuetifyjs.com.

    Multi-step migration

    Several breaking changes in Vuetify 4 can be temporarily reverted by pasting short CSS or configuration snippets โ€” notably CSS reset, typography, elevation, and grid. This means you can migrate incrementally: restore the legacy behavior first, then update each area at your own pace.

    Even though these migrations mostly come down to adjusting CSS classes, manually reviewing every affected template can be time-consuming without automated visual regression tests. For large projects (typically over 200 components), we recommend scanning your codebase for relevant usage before starting:

    • HTML elements โ€” <h1> through <h6> (affected by CSS reset)
    • Grid usage โ€” <v-row> and <v-col>, with specific focus on ad-hoc spacing adjustments (i.e. classes like mx-0, pa-0)
    • Grid attributes โ€” dense, align, justify, order, align-self (affected by grid changes)
    • Shadows โ€” elevation-* classes and elevation attributes or CSS overrides (affected by elevation changes)
    • CSS classes โ€” text-h1 โ€ฆ text-h6, text-subtitle-1, text-body-2, text-caption, text-overline, elevation-*, offset-* (affected by typography)

    Identify the areas with the highest usage first, apply the corresponding compatibility snippets, and then schedule the full class-by-class migration as a follow-up.

    Sections tagged with Codemod Available can be automated using vuetify-codemods.

    Styles

    Style entry points

    There are now pre-compiled entry points for the most common style changes. If you have a Sass file that only sets $color-pack: false or $utilities: false you can replace it with import 'vuetify/styles/core'. See Style entry points for more information.

    CSS reset

    The CSS reset has been mostly removed, with style normalisation being moved to individual components instead. You can inspect the exact changes to learn more. Here is the high level overview:

    • global * { padding: 0; margin: 0; } is gone - no longer resets all elements
    • , , <select> have their browser-native borders and background colors.

    If you notice browser styles adding unnecessary spaces and impact text size, it is recommended to assess the scope of visual regression and selectively apply spacing resets:

    css
    @layer vuetify-core.reset {
      ul, ol, figure, details, summary {
        padding: 0;
        margin: 0;
      }
    
      h1, h2, h3, h4, h5, h6, p {
        margin: 0;
      }
    }

    Restoring most of the previous reset styles would be heavy-handed, but will get the job done as well.

    css
    @layer vuetify-core.reset {
      * { padding: 0; margin: 0; }
      a:active, a:hover { outline-width: 0; }
      code, kbd, pre, samp { font-family: monospace; }
      pre { font-size: 1em; }
      small { font-size: 80%; }
      sub, sup {
        font-size: 75%;
        line-height: 0;
        position: relative;
        vertical-align: baseline;
      }
      sub { bottom: -0.25em; }
      sup { top: -0.5em; }
      textarea { resize: vertical; }
      button,
      input,
      select,
      textarea {
        background-color: transparent;
        border-style: none;
      }
      select {
        -moz-appearance: none;
        -webkit-appearance: none;
      }
      legend {
        display: table;
        max-width: 100%;
        white-space: normal;
      }
    }

    Applying without a build step

    The snippets above are plain CSS and do not require Sass compiler โ€” drop them into any stylesheet, or inline them within <style> block when using the CDN build:

    html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify@4/dist/vuetify.css">
    
    <style>
      @layer vuetify-core.reset {
        ul, ol, figure, details, summary { padding: 0; margin: 0; }
        h1, h2, h3, h4, h5, h6, p { margin: 0; }
      }
    </style>

    Place the <style> block after Vuetify's stylesheet so the layer order declared in vuetify.css takes effect first. Subsequent @layer vuetify-core.reset { โ€ฆ } rules append to the existing layer and won't override component styles.

    Layers

    Cascade layers are now being used everywhere. If you have other styles that are not using @layer they will now always take priority over vuetify.

    If you were already using $layers: true in Vuetify 3, there are now five top-level layers instead of one.

    diff
    - @layer base, vuetify, overrides;
    + @layer base, vuetify-core, vuetify-components, vuetify-overrides, vuetify-utilities, vuetify-final, overrides;

    If you had any usages of @layer vuetify.* in your styles they should be replaced with your own layer name with an appropriate declaration order.

    Layer order declaration must come first

    The layer order @layer statement must be imported before any layered CSS is parsed โ€” including Vuetify's own styles. The browser assigns layer priority the first time a layer name appears, so if Vuetify's styles load first, the browser will establish the order from those, not from your declaration.

    Import your layer order statement at the very top of your app entrypoint:

    js { resource="src/main.ts" }
    // @layer declaration comes first
    import './styles/layers.css'
    import 'vuetify/styles'
    import { createApp } from 'vue'

    If you intend to migrate large application, it is recommended to define and adopt your own layers, so that developers can drop !important and gain more control over the stylesheets.

    css { resource="src/styles/layers.css" }
    @layer vuetify-core;
    @layer vuetify-components;
    @layer vuetify-overrides;
    
    @layer my-app-base;
    @layer my-app-components;
    
    @layer vuetify-utilities;
    
    @layer my-app-utilities;
    
    @layer vuetify-final;

    ::: warning

    If this import is missing or appears after Vuetify styles, reset styles or earlier-declared layers may unexpectedly override component styles. Symptoms vary per app depending on build output order, making it difficult to diagnose. This is often caused by Vite v8.x and/or vue-router v5.x.

    Note: using @vuetify/cli with init command to generate a working project for comparison is usually the fastest way to effectively troubleshoot the problems.

    :::

    Typography {codemod-available}

    The typography system has been updated from Material Design 2 to Material Design 3. The following replacements will have some minor font size differences:

    MD2 (Legacy) MD3 (New)
    text-h1 text-display-large (96px โ†’ 60px)
    text-h2 text-display-large
    text-h3 text-display-medium
    text-h4 text-headline-large
    text-h5 text-headline-small
    text-h6 text-title-large
    text-subtitle-1 text-body-large
    text-subtitle-2 text-title-small
    text-body-1 text-body-large
    text-body-2 text-body-medium
    text-button text-label-large (No uppercase)
    text-caption text-body-small
    text-overline text-label-medium (No uppercase)

    For detailed mapping and migration instructions, see Typography Migration.

    Breakpoints

    The default breakpoints have been reduced to better match modern device sizes:

    Breakpoint Change
    xs 0 (unchanged)
    sm 600px (unchanged)
    md 960px ยป 840px
    lg 1280px ยป 1145px
    xl 1920px ยป 1545px
    xxl 2560px ยป 2138px

    One of the components specifically impacted by those changes is VContainer. See the detailed information about those changes below.

    v3 breakpoints can be restored with the following configuration:

    js { resource="src/plugins/vuetify.ts" }
    export default createVuetify({
      display: {
        thresholds: {
          md: 960,
          lg: 1280,
          xl: 1920,
          xxl: 2560,
        },
      },
    })
    scss { resource="src/styles/_settings.scss" }
    @use 'vuetify/settings' with (
      $grid-breakpoints: (
        'md': 960px,
        'lg': 1280px,
        'xl': 1920px,
        'xxl': 2560px,
      ),
    );

    Elevation {codemod-available}

    Elevation classes (shadows) have been updated to Material Design 3 which uses 6 levels (0-5) instead of 25 (0-24).

    MD3 elevation levels
    elevation-0 (0dp)
    elevation-1 (1dp)
    elevation-2 (3dp)
    elevation-3 (6dp)
    elevation-4 (8dp)
    elevation-5 (12dp)

    * "dp" (density-independent pixels) is a relative unit from Material Design

    See Elevation migration for details and tips to restore legacy MD2 levels if needed.

    Themes

    The default theme has been changed from light to system. This means that the default theme will now be the same as the user's system preference. You can change this by setting the defaultTheme theme option:

    diff { resource="src/plugins/vuetify.ts" }
    export default createVuetify({
    + theme: {
    +   defaultTheme: 'light',
    + },
    })

    Theme colors now support transparency. rgb(var(--v-theme-color)) will continue to work the same as before, but rgba(var(--v-theme-color), 0.8) should be changed to either color-mix(in srgb, rgb(var(--v-theme-color)) 80%, transparent) or rgb(from rgb(var(--v-theme-color)) / 0.8) when used with a transparent theme color.

    Components

    VBtn display

    In Vuetify 3, VField's layout was changed from display: flex to display: grid to better handle its internal elements. However, the grid implementation had limitations with gap control, so in Vuetify 4 we've reverted back to using display: flex.

    The $button-stacked-icon-margin Sass variable has been removed and replaced with $button-stacked-gap. This change allows for more consistent and flexible spacing between elements within the field. If you modified this value, update its variable target:

    diff { resource="styles/styles.scss"}
    @use 'vuetify/settings' with (
    -   $button-stacked-icon-margin: 8px,
    +   $button-stacked-gap,
      );

    VBtn text-transform

    The default text-transform of uppercase has been removed. To restore the previous behavior, set the text-transform prop to uppercase.

    • Set it in the Sass variables for buttons:
    scss
    @use 'vuetify/settings' with (
      $button-text-transform: 'uppercase',
    )
    • Set it as a global default:
    js
    import { createVuetify } from 'vuetify'
    
    const vuetify = createVuetify({
      defaults: {
        VBtn: {
          class: 'text-uppercase',
          // or if you are using $utilities: false
          style: 'text-transform: uppercase;',
        },
      },
    })
    • Manually type uppercase letters:
    diff
    - <v-btn>button</v-btn>
    + <v-btn>BUTTON</v-btn>

    VBadge

    The $badge-dot-border-radius Sass variable has been changed from 4.5px to 50%. Both values produce the same result for the default dot size. If your app increases dot size and prefer them square-ish, you might want to undo the change.

    diff { resource="src/styles/settings/_variables.scss" }
    @use 'vuetify/settings' with (
    -  $badge-dot-border-radius: 4.5px,
    +  $badge-dot-border-radius: 50%,
    );

    VContainer

    Container component won't center the content vertically when paired with fill-height. If you depend on this behavior, you can supplement the missing styles with utility classes:

    diff
    <v-container
    -  class="fill-height"
    +  class="fill-height d-flex align-center flex-wrap"
    />

    Max widths

    The calculation for $container-max-widths has changed to round values down to the nearest 100px for more predictable sizing. With the default breakpoints, this results in the following container widths:

    Breakpoint Change
    md 900px ยป 700px
    lg 1200px ยป 1000px
    xl 1800px ยป 1400px
    xxl 2400px ยป 2000px

    VCounter

    VCounter is used to display the counter hint under VTextField, VTextarea and VFieldInput. The $counter-color and color was replaced in favor of opacity. If you modified this value, move it to target CSS class directly:

    scss { resource="styles/styles.scss"}
    .v-counter {
      opacity: 1;
      color: /* your $counter-color */;
    }

    VDatePicker

    multiple="range" emits only the start and end dates instead of everything in between. Use something like date-fns' eachDayOfInterval if you need all dates in the range.

    diff
    - ['2023-09-28', '2023-09-29', '2023-09-30', '2023-10-01', '2023-10-02']
    + ['2023-09-28', '2023-10-02']

    VFileInput

    Removed the $file-input-details-padding-inline Sass variable.

    diff { resource="src/styles/settings/_variables.scss" }
    @use 'vuetify/settings' with (
    -  $file-input-details-padding-inline: <value>
    +  $input-details-padding-inline: <value>
    );

    VForm {codemod-available}

    Slot variables are no longer refs, read-only values passed to slots are now unwrapped:

    diff
    <VForm>
        <template #default="{ isValid, validate }">
          <VBtn @click="validate" text="validate" />
    -     Form is {{ isValid.value ? 'valid' : 'invalid' }}
    +     Form is {{ isValid ? 'valid' : 'invalid' }}
        </template>
      </VForm>

    The following properties are affected:

    • errors
    • isDisabled
    • isReadonly
    • isValidating
    • isValid
    • items

    VRadioGroup

    Removed the $radio-group-details-padding-inline Sass variable.

    diff { resource="src/styles/settings/_variables.scss" }
    @use 'vuetify/settings' with (
    -  $radio-group-details-padding-inline: <value>
    +  $input-details-padding-inline: <value>
    );

    VSelect/VCombobox/VAutocomplete {codemod-available}

    item in slots has been renamed to internalItem for consistency with VList and VDataTable. item is still available but is now an alias for internalItem.raw which seems like the most common use case.

    You can rename:

    diff
    <VSelect item-title="name">
    -   <template #item="{ item, props }">
    -     <VListItem v-bind="props" :title="item.title" />
    +   <template #item="{ internalItem, props }">
    +     <VListItem v-bind="props" :title="internalItem.title" />
        </template>
      </VSelect>

    Or alias:

    diff
    <VSelect>
    -   <template #item="{ item, props }">
    +   <template #item="{ internalItem: item, props }">
          <VListItem v-bind="props" :title="item.raw.name" />
        </template>
      </VSelect>

    Or remove .raw:

    diff
    <VSelect>
        <template #item="{ item, props }">
    -     <VListItem v-bind="props" :title="item.raw.name" />
    +     <VListItem v-bind="props" :title="item.name" />
        </template>
      </VSelect>

    VSnackbar {codemod-available}

    ::: warning
    This component has its internal HTML structure overhauled to incorporate header and prepend slots
    :::

    Removed the multi-line prop and the $snackbar-multi-line-wrapper-min-height Sass variable. It can be replaced with min-height equivalent.

    diff
    <VSnackbar
        v-model="visible"
    -    multi-line
    +    min-height="68"
        :text="message"
      />

    VSnackbarQueue {codemod-available}

    ::: warning
    This component has been rewritten to enable showing multiple snackbars at once
    :::

    The default slot has been renamed to item. The slot props remain the same.

    diff
    <v-snackbar-queue v-model="messages">
    -  <template v-slot:default="{ item }">
    +  <template v-slot:item="{ item }">
        <v-snackbar v-bind="item" />
      </template>
    </v-snackbar-queue>

    VTextField

    Removed the $text-field-details-padding-inline Sass variable.

    diff { resource="src/styles/settings/_variables.scss" }
    @use 'vuetify/settings' with (
    -  $text-field-details-padding-inline: <value>
    +  $input-details-padding-inline: <value>
    );

    Grid System (VRow and VCol)

    The grid system has been refactored to use CSS gap instead of negative margins on rows and padding on columns. This change provides more flexibility and predictable spacing behavior.

    Layout mechanism changes

    Previous New
    Negative margins (margin: -12px) No margins on VRow
    Gaps from padding No default padding, utilizes CSS gap
    Widths from hardcoded percentage (e.g., 75% for .v-col-9) Calculated width accounting for gaps

    Prop changes on VRow {codemod-available}

    Previous New
    dense density="compact" or gap="8"
    align prop on VRow use utility class (e.g., align-start)
    justify prop on VRow use utility class (e.g., justify-center)
    align-content prop on VRow use utility class (e.g., align-content-center)
    align-sm, justify-md, etc. use responsive utility classes
    no fine-grained control over gap gap prop accepts number, string, or [x, y]

    Prop changes on VCol {codemod-available}

    Previous New
    order prop on VCol use utility class (e.g., order-1)
    props like order-sm, order-md, etc. use responsive utility classes (e.g., order-sm-1)
    align-self prop on VCol use utility class (e.g., align-self-center)
    .offset-{n} (offset classes) offset prop

    Alignment (VRow):

    diff
    - <v-row align="center" justify="space-between">
    + <v-row class="align-center justify-space-between">

    Responsive alignment:

    diff
    - <v-row align-sm="start" align-md="center" justify-lg="end">
    + <v-row class="align-sm-start align-md-center justify-lg-end">

    Order (VCol):

    diff
    - <v-col order="2" order-md="1">
    + <v-col class="order-2 order-md-1">

    Align self (VCol):

    diff
    - <v-col align-self="center">
    + <v-col class="align-self-center">

    Dense rows:

    diff
    - <v-row dense>
    + <v-row density="compact">

    Offset class changes

    Offset classes have been renamed from .offset-* to .v-col-offset-* for namespace consistency:

    diff
    - <v-col offset="3" offset-md="2">
    + <v-col offset="3" offset-md="2">

    The component props (offset, offset-sm, etc.) continue to work unchanged, but if you were using the CSS classes directly, update them:

    diff
    - 
    +

    Sass variables cleanup

    $form-grid-gutter was replaced with $grid-density. New values subtract values from the default gutter

    diff
    - $form-grid-gutter: $spacer * 2 !default;
    + $grid-density: ('default': 0, 'comfortable': -1, 'compact': -2) !default;

    Sass variable $grid-gutters was removed. If your existing project had some custom definition set for this variable, you might want to adjust the variables below:

    scss { resource="src/styles/settings/_variables.scss" }
    @use 'vuetify/settings' with (
      $avatar-margin-end: 8px;
      $avatar-margin-start: 8px;
    
      $icon-left-margin-left: 8px;
      $icon-margin-end: 8px;
      $icon-margin-start: 8px;
    
      $icon-btn-margin-start: 8px;
      $icon-btn-margin-end: 8px;
    }

    Restoring the legacy grid behavior

    If you need to maintain the previous grid behavior (negative margins and column padding), see the Grid Legacy Mode guide.

    Tooling

    Vite: overlay z-index in dev mode

    Vuetify 4 calculates overlay z-index through a shared useStack singleton โ€” when a dialog opens at 2400, any overlay rendered inside it (a select menu, a tooltip, etc.) automatically stacks at 2410. This works correctly in production, but can silently break in Vite dev mode.

    Symptom: Menus, selects, or other overlays opened inside a dialog appear behind it โ€” they render, but are invisible because they sit at the default z-index (2000) instead of stacking above the dialog.

    Root cause: Vite's dependency pre-bundler can serve some Vuetify modules from its optimized cache and others from raw ESM. When this split happens, two separate useStack instances are created. Each overlay registers with its own instance, so they never see each other's stack โ€” and auto-stacking stops working.

    Fix: Force Vite to pre-bundle Vuetify's overlay-related modules consistently, then clear the cache:

    ts { resource="vite.config.ts" }
    export default defineConfig({
      optimizeDeps: {
        include: [
          'vuetify/components/VOverlay',
          'vuetify/components/VDialog',
          'vuetify/components/VMenu',
          'vuetify/components/VSelect',
          'vuetify/components/VTooltip',
        ],
      },
    })

    After updating the config, delete the .vite cache directory and restart the dev server:

    bash
    rm -rf node_modules/.vite

    This issue only manifests in dev mode. Production builds are not affected because Vite bundles everything into a single module graph.

    Defaults

    undefined values are now skipped when merging prop defaults. This button would have been grey in v3, but is now green:

    jsx
    createVuetify({
      defaults: {
        VBtn: { color: 'green' },
      },
    })
    
    <VDefaultsProvider :defaults="{ VBtn: { color: undefined }}">
      <VBtn />
    </VDefaultsProvider>

    Replace undefined with null if you do actually want it to override the global default value.


    File: packages/docs/src/pages/en/getting-started/wireframes.md


    meta:
    title: Wireframes
    keywords: pre-defined layouts, layouts, application layout, material design layouts
    related:

    • /features/application-layout/
    • /features/theme/
    • /features/blueprints/

    Wireframes

    The Vuetify layout system makes it easy to rapidly scaffold an application's UI regions with little effort.

    Examples

    These templates are known as wireframes and are designed to provide a consistent approach to layouts, layering, and shadows. They are a starting point that is meant to be modified to meet the specific needs of your application.

    ::: info
    Additional information on how these templates are structured is located on the Application page.
    :::


    File: packages/docs/src/pages/en/features/accessibility.md


    meta:
    title: Accessibility (a11y)
    keywords: a11y, accessibility, usability
    related:

    • /features/internationalization/
    • /components/menus/
    • /components/lists/
      features:
      label: 'a11y'
      report: true

    Accessibility (a11y)

    Web accessibility (a11y for short), is the inclusive practice of ensuring there are no barriers that prevent the interaction with, or access to, websites on the World Wide Web by people with disabilities. Vuetify components are built to provide keyboard interactions for all mouse-based actions and utilize HTML5 semantic elements where applicable.

    Activator slots

    Vuetify uses activator slots for many components such as v-menu, v-dialog and more. In some instances these activator elements should have specific a11y attributes that associate them with their corresponding content. In order to achieve this, we pass down the necessary a11y options through the slots scope.

    html
    <template>
      <v-menu>
        <template v-slot:activator="{ props }">
          <v-btn
            text="Click me"
            v-bind="props"
          ></v-btn>
        </template>
    
        <v-list>
          <v-list-item @click="method">
            <v-list-item-title>Option 1</v-list-item-title>
          </v-list-item>
    
          <v-list-item disabled>
            <v-list-item-title>Option 2</v-list-item-title>
          </v-list-item>
    
          <v-list-item @click="method">
            <v-list-item-title>Option 3</v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </template>

    When the activator element is rendered, it will now contain the bound a11y attributes:

    html
    Click me

    Focus management and keyboard interactions

    Beyond attributes, components such as v-menu also support interaction by pressing โ†‘ and โ†“ for navigating between options.

    v-menu

    When inside of a v-menu, v-list-item will be automatically configured to have a role of menuitem. Navigate to the Menu for more information on the components features.

    Additional Resources

    While Vuetify attempts to make a11y as easy as possible in your application, there are times where additional information is needed. Below you can find a list of helpful resources.