結論

Vuetify(ビューティファイ)は、Vue 3 の上で Material Design の部品(ボタン・フォーム・表・ダイアログなど)を <v-btn> のようなタグで並べて画面を作る UI コンポーネント集です。2026年10月29日時点の最新は 4.3.1 で、Vite のプラグインを使うと「使った部品だけ」がビルドに入ります。

この記事でわかること

  • Vite+Vue 3 に Vuetify 4 を入れて、骨組み・ボタン・フォーム・一覧・ダイアログ・ダークテーマを動かした画面と計測値
  • 全部登録・使った部品だけ・SVG アイコンの3通りでビルドしたサイズと、ブラウザが実際に受け取ったバイト数
  • v-app が無い・アイコンが出ない・Vuetify 2 の書き方・SASS 未導入のエラー原文と直し方、他ライブラリとの判断表

2026年10月29日更新|Vuetify 4.3.1・Vue 3.5.44・Vite 8.3.5・Chromium 153 で実行確認

Vue は「データが変わったら画面を描き直す」仕組みを持つ土台で、Vuetify はその上に乗る部品箱です。ボタンの見た目や表の並べ替えを自分で CSS と JavaScript で作る代わりに、Vuetify の部品を置いて属性で調整します。

flowchart TD
    A[Vue 3<br>データと描画の土台] --> B[Vuetify 4<br>部品箱 105種]
    B --> C[v-app / v-btn / v-form<br>v-data-table / v-dialog]
    C --> D[自分の画面<br>テーマ色・密度・幅で調整]

よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
vuetify とは Vue 3 用の Material Design の UI コンポーネント集(MIT ライセンス) Vuetifyとは
vuetify 使い方(入れ方) npm i vuetify → createVuetify() を app.use()。新規なら npm create vuetify@latest インストールと初期設定
最初に書くもの 一番外側に <v-app>。無いと画面が真っ白になる 画面の骨組み
どの版を使うか 新規は 4.x。3.x は 2027年7月27日まで LTS、2.x は終了済み バージョンの選び方
ダークモード useTheme().change('dark')。v4 は既定が OS の設定に従う テーマ・密度・レスポンシブ
サイズを減らすには vite-plugin-vuetify の autoImport と SVG アイコン。手元では 2.0MB → 0.76MB ビルドサイズの実測
アイコンが出ない @mdi/font の CSS を読み込んでいない。エラーは出ず空白になる よくあるエラー
Element Plus 等との違い 見た目の流儀(Material か否か)と部品数・周辺機能で選ぶ 他の UI ライブラリとの違い

確認環境:Ubuntu 24.04.5 LTS の上で、Node.js 22.23.4・npm 10.9.9 を使い、作業用フォルダーに Vite 8.3.5・@vitejs/plugin-vue 6.0.10・Vue 3.5.44・Vuetify 4.3.1・vite-plugin-vuetify 2.1.3・@mdi/font 7.4.47・@mdi/js 7.4.47・sass-embedded 1.107.0 を npm で入れ、社員名簿(ボタン・登録フォーム・一覧・削除ダイアログ・テーマ切替)のサンプルを作りました。画面と計測値は Vite の開発サーバー(127.0.0.1:5173)と vite build の出力を Python の http.server で配信したものを、Chromium 153.0.8010.12(Playwright 1.63.0・日本語ロケール)で開いて取得しています。新規作成は create-vuetify 3.2.1 を対話なしで実行しました。版の日付・サポート期限・ブラウザ対応・v3 から v4 の変更点は Vuetify 公式ドキュメント(GitHub 上の原稿を含む)と npm のレジストリで確かめ、Nuxt と Vuetify 2 の書き方は公式ドキュメントの範囲で書いています。図は mermaid で描画を確かめています(確認日 2026年10月29日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Vuetifyとは・使い方|v4の導入からフォーム・一覧・テーマまで実測」

Vuetifyとは(Vue の UI コンポーネント集)

この節では、Vuetify が何をしてくれるもので、Vue との関係がどうなっているかが分かります。

Vuetify は、Google の Material Design に沿った見た目と動きを持つ部品を、Vue 3 のコンポーネントとして提供するライブラリです。 公式の FAQ は「Vuetify は Vue.js の上に作られたコンポーネント集であり、Vue.js は UI を作るための JavaScript フレームワーク」と両者を分けて説明しています。ライセンスは MIT で、無料で商用にも使えます。

105種同梱のコンポーネント4.3.1 の lib/components の数。labs は別に 15種
4.3.1最新版(2026年10月29日時点)2026年10月26日公開。4.0.0 は2月23日
36pxv-btn の既定の高さcomfortable 28px・compact 24px(実測)

手元で node_modules/vuetify/lib/components を数えると V で始まるフォルダーが 105 あり、VBtn・VForm・VDataTable・VDialog・VNavigationDrawer のほか、VCalendar・VDatePicker・VStepper・VColorPicker・VOtpInput まで入っています。開発中の部品(VCommandPalette・VMaskInput・VHeatmap など 15種)は vuetify/labs に分かれています。

何が楽になるか

  • 見た目を作らなくてよい:ボタンの影・押したときの波紋・入力欄のラベルの浮き上がり・表の並べ替え矢印が最初から付いています。
  • レイアウトが決まっている:アプリバー・左のメニュー・本文の位置関係を v-app が計算します。手元では本文(v-main)の左の余白が、メニューの幅と同じ 256px に自動で設定されていました。
  • テーマで一括変更:色の名前(primary など)を1か所で決めると、全部品に反映されます。ダークモードも1行で切り替わります。
  • 日本語の文言が同梱:vuetify/locale の ja を渡すと、表の「1ページあたりの件数」などが日本語になります。

Vuetifyのバージョンの選び方(v4・v3・v2 とサポート期限)

この節では、2026年10月29日時点でどの版を使うべきか、各版のサポート期限と必要な Vue の版が分かります。

新しく始めるなら 4.x です。 npm の latest タグは 4.3.1 を指し、3.x は v3-stable タグ(3.13.7)として残っています。公式の Long-term support ページの表は次のとおりです。

版 状態 公開日 LTS 終了日 必要な Vue
Vuetify 4.x Active(開発中) 2026年2月23日 (次の大きな版の後) 3.5 以上
Vuetify 3.x Maintained(保守) 2022年11月1日 2027年7月27日 3.0 以上
Vuetify 2.7 Archived(終了) 2019年7月23日 2025年1月23日 2.x
Vuetify 1.5 Archived(終了) 2019年2月5日 2020年7月31日 2.x

4.3.1 の package.json の peerDependencies は vue: ^3.5.0 || ^3.6.0-0 で、Vue 3.4 以前には入りません。対応ブラウザは公式の Browser support ページで Chromium 系 119 以上・Firefox 128 以上・Safari 16.4 以上で、Internet Explorer は非対応です。Chromium 99〜118 と Firefox 97〜127 は「一部対応」で、相対色構文(rgb(from …))が使えないため一部の色が正しく出ないと注記されています。

手元で npm の公開日を引くと、4.x は 4.0.0(2月23日)→ 4.1.0(6月2日)→ 4.2.0(9月2日)→ 4.3.0(10月19日)→ 4.3.1(10月26日)と、ほぼ月に1回以上の更新が続いています。3.x も 3.13.7(10月14日)まで修正が出ています。

Vuetifyの使い方(1)インストールと初期設定

この節では、Vite+Vue 3 のプロジェクトに Vuetify 4 を入れて最初の画面を出すまでの手順と、新規なら npm create vuetify で何ができるかが分かります。

既存の Vue 3 プロジェクトなら、パッケージを入れて createVuetify() を app.use() に渡すだけです。 使った部品だけをビルドに入れるため、vite-plugin-vuetify も一緒に入れます。

1

パッケージを入れる

npm install vuetify @mdi/font vite-plugin-vuetify。手元では Vuetify 4.3.1・@mdi/font 7.4.47・vite-plugin-vuetify 2.1.3 が入り、node_modules は 178MB になった(Vue・Vite 含む。後で入れた sass-embedded で 239MB)。

@mdi/font はアイコン

2

vite.config.js にプラグインを足す

vuetify({ autoImport: true }) を vue() の後ろに置く。公式は「Vue プラグインの後に Vuetify プラグインを置く」と明記している。

順番に注意

3

plugins/vuetify.js を作る

'vuetify/styles' とアイコンの CSS を読み込み、createVuetify({ ... }) でテーマ・ロケール・既定値を決めて export する。

設定は1か所に

4

main.js で登録する

createApp(App).use(vuetify).mount('#app')。use を忘れると「Could not find defaults instance」で止まる(よくあるエラーの節)。

忘れると真っ白

5

App.vue の一番外側を v-app にする

<v-app><v-main>…</v-main></v-app>。npm run dev で 127.0.0.1:5173 を開く。手元では Vite が 984ms で起動した。

v-app 必須

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vuetify from 'vite-plugin-vuetify'

export default defineConfig({
  plugins: [
    vue(),
    vuetify({ autoImport: true }),   // vue() の後ろに置く
  ],
})
// src/plugins/vuetify.js
import 'vuetify/styles'
import '@mdi/font/css/materialdesignicons.css'
import { createVuetify } from 'vuetify'
import { ja, en } from 'vuetify/locale'

export default createVuetify({
  locale: { locale: 'ja', fallback: 'en', messages: { ja, en } },
  theme: {
    defaultTheme: 'light',
    themes: {
      light: { colors: { primary: '#1565C0', secondary: '#00897B' } },
      dark:  { colors: { primary: '#90CAF9', secondary: '#80CBC4' } },
    },
  },
  defaults: {
    VBtn: { variant: 'flat' },
    VTextField: { variant: 'outlined', density: 'comfortable' },
  },
})
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'

createApp(App).use(vuetify).mount('#app')

defaults は部品ごとの既定値です。上の例では、全部の v-btn が variant="flat"、全部の v-text-field が枠線つきになります。手元の画面でも、variant を書いていないボタンの class に v-btn--variant-flat が付いていました。

新規なら create-vuetify

公式が推奨する新規作成は npm create vuetify@latest です。手元で create-vuetify 3.2.1 を対話なしで実行しました。

$ npm create vuetify@latest -- --name scaffold --platform vue --router router --css none --packageManager npm --no-typescript
T  Create Vuetify v3.2.1
o  Template downloaded
o  Configuration applied
o  Converted to JavaScript
—  scaffold has been generated at scaffold

T-Next steps-----------------------------T
|  cd scaffold                           |
|  npm install                           |
|  npm run dev                           |
—----------------------------------------—

生成された package.json の依存は vuetify ^4.0.2・vue ^3.5.30・vue-router ^5.0.3・@mdi/font 7.4.47・@fontsource/roboto・vite ^8.0.0・vite-plugin-vuetify ^2.1.3・sass-embedded・unplugin-fonts でした。src/plugins/vuetify.js は defaultTheme: 'system'、vite.config.mjs は autoImport: true と styles.configFile: 'src/styles/settings.scss' が設定され、AGENTS.md(AI コーディング支援向けの決まり)まで作られます。--help で見えた選択肢は次のとおりです。

オプション 選べる値 意味
--platform vue / nuxt Vue 単体か Nuxt か
--router router / file-router / none vue-router の有無。file-router はファイル名でルートを作る
--features pinia, eslint, i18n, mcp 状態管理・静的検査・多言語・Vuetify MCP
--css unocss / tailwindcss / none 等 ユーティリティ CSS を併用するか
--no-typescript — 既定は TypeScript。JavaScript にする
--preset Base / Full / Vuetify0 組み合わせの雛形

Vue 自体のプロジェクト作成(create-vue)とフォルダー構成は、関連記事「Vue環境構築|create-vueでプロジェクト作成とディレクトリ構成」で扱っています。vite.config の書き方は、関連記事「vite.configの書き方|用途別コピペ一覧とVite 8の変更点」にまとめています。

Vuetifyの使い方(2)画面の骨組み:v-app・v-app-bar・v-navigation-drawer・v-main

この節では、アプリバー・左メニュー・本文の骨組みをどう書き、Vuetify がどう位置を計算しているかが分かります。

v-app が一番外側、v-main が本文で、v-app-bar と v-navigation-drawer はその間に置きます。 本文の余白は Vuetify が自動で計算します。

<template>
  <v-app>
    <v-app-bar color="primary" density="compact">
      <v-app-bar-nav-icon @click="drawer = !drawer" />
      <v-app-bar-title>社員名簿(Vuetify 4 サンプル)</v-app-bar-title>
      <v-btn icon="mdi-theme-light-dark" @click="toggleTheme" aria-label="テーマ切替" />
    </v-app-bar>

    <v-navigation-drawer v-model="drawer">
      <v-list density="compact" nav>
        <v-list-item prepend-icon="mdi-view-dashboard" title="ダッシュボード" value="home" />
        <v-list-item prepend-icon="mdi-account-multiple" title="社員名簿" value="members" active />
        <v-list-item prepend-icon="mdi-cog" title="設定" value="settings" />
      </v-list>
    </v-navigation-drawer>

    <v-main>
      <v-container>
        ここに本文
      </v-container>
    </v-main>
  </v-app>
</template>

Chromium で描画した結果を計測すると、次のようになっていました。

要素 計測した値 意味
.v-application の class v-theme--light v-layout v-layout--full-height v-locale--is-ltr テーマ名・レイアウト・文字方向が class で付く
v-app-bar の背景色 rgb(21, 101, 192) テーマの primary(#1565C0)がそのまま使われる
v-main の padding 左 256px・上 48px メニューの幅 256px と compact のアプリバーの高さ 48px を自動で確保
フォント Roboto, sans-serif Roboto は同梱されない。入れなければ sans-serif で表示

v-main には --v-layout-left: 256px のような CSS 変数が付き、メニューを閉じると 0px に変わります。この計算を担っているのが v-app(正確にはその中の layout)で、v-app の外に v-app-bar を置くと「Could not find injected layout」で止まります(よくあるエラーの節)。

フォントについて、公式は「既定のフォントは Roboto だが、自分で読み込む」と書いています。create-vuetify の雛形は @fontsource/roboto と unplugin-fonts で読み込む形になっていました。手元のサンプルは読み込んでいないため、日本語はシステムのゴシック体で表示されています。

Vuetifyの使い方(3)v-btn・v-form と入力検証

この節では、ボタンの6つの見た目と、フォームの入力検証(必須・メール形式・文字数)の書き方と、画面に出た文言が分かります。

ボタンは variant で見た目、color で色、density で高さを変えます。 同じ primary 色で6種類を並べ、Chromium で背景色と文字色を取りました。

variant 背景 文字色 見え方
elevated(既定) rgb(21, 101, 192) 白 塗りつぶし+影。class に v-btn--elevated
flat rgb(21, 101, 192) 白 塗りつぶし、影なし
tonal 透明+薄い色の重ね primary 淡い背景。背景は transparent で疑似要素が色を重ねる
outlined 透明 primary 枠線だけ
text 透明 primary 文字だけ。ホバーで薄く色が付く
plain 透明 primary(薄め) 文字だけで、ホバーの背景も無い

高さは density で変わり、default 36px・comfortable 28px・compact 24px でした。text-transform は none で、v4 では英字が自動で大文字になりません(v3 までは uppercase が既定。移行の節)。

<v-btn color="primary" variant="tonal">tonal</v-btn>
<v-btn color="primary" prepend-icon="mdi-plus">追加</v-btn>
<v-btn color="error" loading>loading</v-btn>
<v-btn disabled>disabled</v-btn>
<v-btn icon="mdi-delete" size="small" variant="text" color="error" aria-label="削除" />

v-form と rules

入力検証は、各入力部品の rules に「正しければ true、誤りなら文言の文字列」を返す関数を渡します。v-form の validate() が全部の部品をまとめて確かめます。

<v-form ref="form" @submit.prevent="submit">
  <v-text-field v-model="name" label="氏名" :rules="[rules.required, rules.max20]" counter="20" />
  <v-text-field v-model="email" label="メール" :rules="[rules.required, rules.email]" type="email" />
  <v-select v-model="dept" :items="depts" label="部署" :rules="[rules.required]" />
  <v-checkbox v-model="agree" label="内容を確認した" :rules="[v => !!v || '確認が必要です']" />
  <v-btn type="submit" color="primary" prepend-icon="mdi-content-save">登録</v-btn>
</v-form>
const rules = {
  required: v => !!v || '必須項目です',
  email: v => /.+@.+\..+/.test(v) || 'メールアドレスの形式で入力します',
  max20: v => (v || '').length <= 20 || '20文字以内で入力します',
}

async function submit() {
  const { valid } = await form.value.validate()
  if (!valid) return
  items.value.push({ id: nextId(), name: name.value, dept: dept.value, email: email.value })
  form.value.reset()
}

何も入力せずに「登録」を押すと、4つの部品に v-input--error が付き、.v-messages__message に次の文言が出ました。

必須項目です
必須項目です
必須項目です
確認が必要です

メール欄に「abc」と打つと、入力中に「メールアドレスの形式で入力します」に変わります。正しく入力して登録すると、一覧の下の件数表示が「1-5 件目 / 12件」から「1-5 件目 / 13件」になり、v-snackbar に「新井 太郎 を登録しました」と出ました。

v4 の組み込みルール(createRulesPlugin)

Vuetify 4 には '$required' のような名前で使える組み込みのルールがあります。使うには createRulesPlugin を登録します。

import { createVuetify, createRulesPlugin } from 'vuetify'
const vuetify = createVuetify({ locale: { locale: 'ja', messages: { ja, en } } })
app.use(vuetify).use(createRulesPlugin({}, vuetify.locale))
<v-text-field v-model="v" label="氏名" :rules="['$required', ['$maxLength', 5]]" />
<v-text-field v-model="m" label="メール" :rules="['$email']" />

手元で6文字と「abc」を入れると、ja ロケールの文言で次のように出ました。

最大5文字まで入力してください
有効なメールアドレスを入力してください

引数のあるルールは ['$maxLength', 5] のように配列で書きます。'$maxLength(5)' と文字列で書くと、ルールが undefined になり、コンソールに undefined is not a valid value. Rule functions must return boolean true or a string. が出て検証されませんでした。また、createRulesPlugin を登録し忘れると、エラーは出ずに画面に「$required」「$email」という文字がそのまま表示されました。

Vuetifyの使い方(4)v-data-table・v-dialog・v-snackbar

この節では、一覧表の並べ替え・検索・ページ分け、削除確認ダイアログ、通知の書き方と、動かして分かった注意点が分かります。

v-data-table は headers(列の定義)と items(行の配列)を渡すだけで、並べ替え・ページ分け・件数表示が付きます。 search を渡すと全列を対象に絞り込みます。

<v-text-field v-model="search" label="検索" prepend-inner-icon="mdi-magnify" clearable max-width="320" />
<v-data-table :headers="headers" :items="items" :search="search" :items-per-page="5">
  <template #item.dept="{ value }">
    <v-chip size="small" :color="value === '開発部' ? 'primary' : 'secondary'">{{ value }}</v-chip>
  </template>
  <template #item.actions="{ item }">
    <v-btn icon="mdi-delete" size="small" variant="text" color="error" @click="askDelete(item)" />
  </template>
</v-data-table>
const headers = [
  { title: 'ID', key: 'id', align: 'end' },
  { title: '氏名', key: 'name' },
  { title: '部署', key: 'dept' },
  { title: 'メール', key: 'email' },
  { title: '操作', key: 'actions', sortable: false },
]

12人分のデータで動かした結果です。

操作 結果(Chromium で取得)
初期表示 5行表示。下に「1ページあたりの件数:5」「1-5 件目 / 12件」(ja ロケールの文言)
「氏名」の見出しを1回押す aria-sort="ascending" が付き、伊藤→加藤→吉田→高橋→佐藤 の順
もう1回押す 降順。鈴木→渡辺→田中→中村→新井
検索欄に「営業」 営業部の5人だけになり「1-5 件目 / 5件」
density を compact 行の高さ 51.7px → 41px(comfortable は 44px)

注意したいのは並べ替えの順です。 「伊藤→加藤→吉田→高橋→佐藤」は五十音順ではなく、漢字の文字コード順です。日本語の名前を五十音で並べたいときは、読み仮名の列(yomi など)をデータに持たせて、その列で並べ替えるか、headers の sort に Intl.Collator('ja') を使う比較関数を渡します。

const collator = new Intl.Collator('ja')
const headers = [
  { title: '氏名', key: 'name', sort: (a, b) => collator.compare(a, b) },
]

v-dialog(削除の確認)

<v-dialog v-model="dialog" max-width="400">
  <v-card title="削除の確認" :text="`${target?.name} を一覧から削除します。`">
    <v-card-actions>
      <v-spacer />
      <v-btn variant="text" @click="dialog = false">やめる</v-btn>
      <v-btn color="error" @click="doDelete">削除する</v-btn>
    </v-card-actions>
  </v-card>
</v-dialog>
<v-snackbar v-model="snackbar" :timeout="2000">{{ snackText }}</v-snackbar>

ゴミ箱のボタンを押したときの状態を計測しました。

  • ダイアログの要素に role="dialog" と aria-modal="true" が付いていた。
  • 背景(scrim)は黒・不透明度 0.32、ダイアログの z-index は 2400。
  • フォーカスはダイアログの中身(.v-overlay__content)へ移り、<html> に v-overlay-scroll-blocked が付いて背景のスクロールが止まった。
  • Esc キーで閉じ、「削除する」を押すと一覧が「1-5 件目 / 12件」に減り、snackbar に「鈴木 花子 を削除しました」と出た。

テーマ(色・ダークモード)・密度・レスポンシブ

この節では、色の決め方、ダークモードの切り替え、画面幅で変わる動き(ブレークポイント)を実測値つきで説明します。

テーマは createVuetify({ theme }) で色を決め、useTheme() で切り替えます。 Vuetify 4 では defaultTheme の既定が 'system'(OS の設定に従う)に変わりました。

import { useTheme } from 'vuetify'
const theme = useTheme()
function toggleTheme() {
  theme.change(theme.global.name.value === 'dark' ? 'light' : 'dark')
}
計測項目 light dark
.v-application の class v-theme--light v-theme--dark
背景色 rgb(255, 255, 255) rgb(18, 18, 18)
CSS 変数 --v-theme-primary 21,101,192(#1565C0) 144,202,249(#90CAF9)
アプリバーの背景 rgb(21, 101, 192) rgb(144, 202, 249)
color-scheme light dark(スクロールバーも暗くなる)

色は <style id="vuetify-theme-stylesheet">(手元では 13,192 文字)に CSS 変数として書き出され、切り替えると変数が入れ替わります。自分の CSS からも rgb(var(--v-theme-primary)) で参照できます。v4 ではテーマ色が透過に対応したため、rgba(var(--v-theme-primary), 0.8) の書き方は rgb(from rgb(var(--v-theme-primary)) r g b / 0.8) か color-mix() に変えるよう公式の移行ガイドに書かれています。

defaultTheme を書かずに起動した画面を、Chromium のダークモード設定(prefers-color-scheme: dark)で開くと v-theme--dark・背景 rgb(18, 18, 18) になり、ライト設定では白になりました。以前のように常にライトで出したいときは defaultTheme: 'light' を明示します。

密度(density)

density は default・comfortable・compact の3段階で、ボタン・入力欄・表・リストに共通です。社内の業務画面のように1画面に多くの情報を出すなら compact、スマホで指で押すなら default が向きます。手元の計測は、ボタン 36→28→24px、表の行 51.7→44→41px でした。

ブレークポイントと useDisplay

画面幅の区分(ブレークポイント)は v4 で Material Design 3 の値に変わりました。useDisplay() の name を表示しながら、Chromium の幅を変えて確かめた結果です。

幅(px) name v-container の幅 左メニュー
1545 xl 1289(本文いっぱい) 常時表示
1544 lg 1000(上限) 常時表示
1145 lg 889 常時表示
1144 md 700(上限) 隠れる(temporary)
840 / 839 md / sm 700 / 839 隠れる
600 / 599 sm / xs 600 / 599 隠れる

境目は xs/sm が 600px、sm/md が 840px、md/lg が 1145px、lg/xl が 1545px でした。公式の移行ガイドにある v3 → v4 の変更(md 960→840、lg 1280→1145、xl 1920→1545、xxl 2560→2138)と一致します。v-navigation-drawer は lg 未満で自動的に「重ねて表示(temporary)」になり、v-main の左余白が 256px → 0px に変わりました。v-container の上限も md 700px・lg 1000px で、v3 の 900px・1200px より狭くなっています。

import { useDisplay } from 'vuetify'
const { mdAndUp, name, width } = useDisplay()
// mdAndUp.value が true なら 840px 以上

アイコンの使い方(@mdi/font と @mdi/js)

この節では、アイコンを出す2つの方法と、それぞれの大きさ・書き方の違いが分かります。

Vuetify 自体はアイコンを同梱していません。 公式のインストール手順も「アイコンを入れるのを忘れずに」と注意し、例として @mdi/font を挙げています。

アイコンの入れ方

@mdi/fontCSS(418KB・7,474 クラス)とフォント(woff2 403KB)を読み込み、icon="mdi-home" と名前で書く。手軽だが、使わない 7,000 個分も配信される
↔
@mdi/jsimport { mdiHome } from '@mdi/js' で SVG のパスを渡す。使ったアイコンだけがビルドに入り、フォントの読み込みが無い。書く量は増える

手元の差:CSS 653KB → 330KB、フォント 403KB → 0

// @mdi/js を使う場合の plugins/vuetify.js
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'
import { mdiHome, mdiDelete } from '@mdi/js'

export default createVuetify({
  icons: {
    defaultSet: 'mdi',
    aliases: { ...aliases, home: mdiHome, delete: mdiDelete },
    sets: { mdi },
  },
})
<!-- 名前で書く(@mdi/font) -->
<v-btn prepend-icon="mdi-home">ホーム</v-btn>
<!-- 別名で書く(@mdi/js。aliases に登録した名前に $ を付ける) -->
<v-btn prepend-icon="$home">ホーム</v-btn>

@mdi/font では <i class="mdi-home mdi v-icon"> が描画され、::before の content に私用領域の文字(フォントの字形)が入ります。@mdi/js では <i class="v-icon"> の中に <svg class="v-icon__svg" viewBox="0 0 24 24"> が入りました。どちらも幅 24px で、見た目は同じです。

@mdi/font を入れてビルドすると、woff2(403KB)のほかに woff(588KB)・ttf(1,308KB)・eot(1,308KB)も dist にコピーされます。ただし Chromium が実際に読み込んだのは woff2 の1つだけでした(次の節)。

ビルドサイズの実測(ツリーシェイク・アイコン方式)

この節では、同じ社員名簿の画面を3通りの設定でビルドし、ファイルの大きさとブラウザが受け取ったバイト数、ビルド時間がどれだけ違うかが分かります。

「全部登録」から「使った部品だけ+SVG アイコン」に変えると、ブラウザが受け取る量は 2.04MB から 0.76MB に減りました。 vite build の出力(gzip 前後)と、配信して Chromium が受け取った合計です。

2.04MB全部登録+@mdi/fontJS 767KB・CSS 865KB・woff2 403KB
1.48MBautoImport+@mdi/fontJS 420KB・CSS 653KB・woff2 403KB
0.76MBautoImport+@mdi/jsJS 431KB・CSS 330KB・フォント無し
設定 JS(gzip) CSS(gzip) 受け取った合計 ビルド
全部登録(components・directives を import)+@mdi/font 766.66KB(248.05KB) 864.71KB(126.53KB) 2,035,015 B 1.87秒・1,066 モジュール
autoImport(vite-plugin-vuetify)+@mdi/font 419.86KB(141.52KB) 652.99KB(100.18KB) 1,476,481 B 1.50秒・752 モジュール
autoImport+@mdi/js(SVG) 431.42KB(146.19KB) 329.54KB(46.37KB) 761,384 B 0.82秒・753 モジュール
参考:Vuetify なしの素の Vue 63.15KB(24.93KB) — 63,496 B 0.14秒・10 モジュール

ビルドした JS の中身を調べると、全部登録では使っていない v-calendar(37か所)・v-date-picker(54か所)・v-stepper(34か所)の文字列が含まれ、autoImport では 0 でした。CSS でも .v-calendar の規則が全部登録では6つ、autoImport では0でした。

autoImport でも CSS が 330KB 残るのは、ユーティリティクラス(d-flex・ma-2 など。手元の概算で約 131KB)と色のクラス(bg-deep-purple など。約 44KB)が vuetify/styles に含まれるためです。SASS 変数の $color-pack: false・$utilities: false で減らせます(次の節)。

読み込み時間は、同じ PC の 127.0.0.1 からの配信で、全部登録 load 416ms・autoImport 431ms・SVG 321ms・素の Vue 50ms でした。回線が遅いほど受け取る量の差が効きます。他の Vue 用 UI ライブラリと同じ画面で比べた結果は、関連記事「Vue UIライブラリ比較|6種で同じ画面を作りサイズを実測」にあります。

  • 1vite-plugin-vuetify の autoImport を使うJS 767KB → 420KB。import * as components の行は消す
  • 2アイコンは @mdi/js にするCSS 653KB → 330KB、フォント 403KB が不要に
  • 3動的コンポーネントは手で import する<component :is> はプラグインが解析できないと公式が明記
  • 4使わない色・ユーティリティは SASS で切る$color-pack: false で約 44KB、$utilities: false で約 131KB(概算)

SASS 変数とユーティリティクラスでのカスタマイズ

この節では、角の丸さなど部品の既定値を SASS 変数で一括して変える方法と、ビルド時間への影響が分かります。

部品ごとの細かい既定値(角の丸さ・余白・文字の変形など)は、vuetify/settings の SASS 変数を上書きします。 これには sass(公式の雛形は sass-embedded)が要ります。

// src/styles/settings.scss
@use 'vuetify/settings' with (
  $button-border-radius: 20px,
  $card-border-radius: 16px
);
// vite.config.js
vuetify({ autoImport: true, styles: { configFile: 'src/styles/settings.scss' } })

sass-embedded を入れずにビルドすると、次のエラーで止まりました。

✗ Build failed in 810ms
error during build:
Build failed with 49 errors:
[plugin vite:css] virtual:plugin-vuetify:styles/main.sass
Error: Preprocessor dependency "sass-embedded" not found. Did you install it? Try `npm install -D sass-embedded`.

npm install -D sass-embedded の後は成功し、出力の CSS に border-radius:20px が入っていました。ただしビルド時間は 1.50秒から 9.23秒に伸びました(Vuetify の全 SASS をコンパイルし直すため)。変数を変える必要が無いうちは configFile を付けないほうが開発が軽くなります。

ユーティリティクラス

余白や並びは、Vuetify に同梱のクラスで書けます。サンプルでは class="d-flex flex-wrap ga-2 mb-6"(横並び・折り返し・隙間 8px・下の余白 24px)を使いました。数字は 4px 単位で、ma-2 は margin 8px、pa-4 は padding 16px です。文字の大きさは v4 で Material Design 3 の名前(text-headline-small・text-body-large など)になり、v3 の text-h5 などは移行の対象です。

Vuetify 2・3・4 の違いと移行

この節では、検索で出てくる以前の書き方(Vuetify 2)がなぜ動かないのか、v3 から v4 で何が変わったのかが分かります。

Vuetify 2 は Vue 2 用で、new Vuetify()・Vue.use(Vuetify) と書きます。Vuetify 3 以降は Vue 3 用で、createVuetify()・app.use() です。 手元で Vuetify 4 に v2 の書き方をすると、次のエラーで止まりました。

// import Vuetify from 'vuetify'; new Vuetify({})
SyntaxError: The requested module '/node_modules/.vite/deps/vuetify.js' does not provide an export named 'default'

// import * as Vuetify from 'vuetify'; new Vuetify.default({})
TypeError: Vuetify.default is not a constructor
項目 Vuetify 2 Vuetify 3 Vuetify 4
Vue 2.x 3.0 以上 3.5 以上
初期化 new Vuetify() createVuetify() createVuetify()
値の受け渡し value model-value model-value
デザイン Material Design 2 MD2 寄り Material Design 3(字体・影・幅)
既定テーマ light light system(OS に従う)
ボタンの英字 大文字 大文字 そのまま
サポート 2025年1月に終了 2027年7月27日まで LTS 開発中

v3 → v4 で変わった主な点(公式の移行ガイド)

  1. 1ブレークポイントmd 960→840、lg 1280→1145、xl 1920→1545、xxl 2560→2138px。display.thresholds で v3 の値に戻せる
  2. 2文字クラスtext-h5→text-headline-small、text-body-1→text-body-large など MD3 の名前に。codemod で変換できる
  3. 3影(elevation)0〜24 の 25段階から 0〜5 の 6段階に
  4. 4グリッド(v-row・v-col)負のマージンから CSS gap に。dense・justify・order などの prop はユーティリティクラスへ
  5. 5CSS リセットとレイヤー* { margin:0; padding:0 } が無くなり、自分の CSS が Vuetify より優先される。レイヤーは5つに
  6. 6v-container上限が md 900→700、lg 1200→1000、xl 1800→1400px。fill-height で縦中央にならなくなった
  7. 7v-form のスロットisValid などが ref でなくなり .value を付けない

公式は変換ツール vuetify-codemods と、Vuetify MCP の get_v4_breaking_changes で変更箇所を見つける方法を案内しています。Vue 2 のアプリは、先に Vue 3 へ移行してから Vuetify 2 → 3 → 4 の順に上げます。

他の UI ライブラリとの違い(Element Plus・Quasar・PrimeVue・Tailwind)

この節では、Vue 用の主な UI ライブラリと Vuetify を、見た目の流儀・部品数・周辺機能で比べ、どれを選ぶかの判断表が分かります。

違いは「見た目の流儀を決めてもらうか」と「部品以外に何が付くか」です。 2026年10月29日時点の npm の最新版で整理しました(部品数は各公式の一覧、ライセンスは npm の表記)。

ライブラリ(版) 見た目の流儀 特徴 向く場面
Vuetify(4.3.1) Material Design 3 部品 105種+labs、レイアウト・テーマ・日本語文言が同梱。MIT Google 風の見た目でよい業務アプリ・管理画面を速く作る
Element Plus(2.14.7) 独自(Element の流儀) 表・フォームが豊富。中国語圏で利用が多い。MIT Material でない、落ち着いた管理画面
Quasar(2.35.2) Material(独自調整) 部品に加え CLI で SPA・SSR・PWA・モバイル・デスクトップを1つのコードから。MIT Web とアプリを同じコードで出したい
PrimeVue(5.0.4) 複数のテーマ+unstyled 見た目なしモードで Tailwind と組める。ライセンスは npm の LICENSE.md を参照 独自デザインを Tailwind で付けたい
Tailwind CSS(4.3.3) 無し(ユーティリティ CSS) 部品ではなくクラスの集まり。Vue 専用でもない。MIT デザイナーの指定どおりに1から作る
1

Vuetify を選ぶ

見た目を決めてもらい、表・フォーム・ダイアログを揃えて速く作りたい。Material Design に抵抗が無い。

業務アプリ・社内ツール

2

Quasar を選ぶ

同じコードから Web・PWA・スマホアプリ・デスクトップまで出したい。

マルチプラットフォーム

3

PrimeVue+Tailwind を選ぶ

部品の動きは借りて、見た目は会社のデザインに合わせたい。

独自デザイン

4

Tailwind だけで作る

デザインの指定が細かく、部品の見た目を上書きするより1から書くほうが早い。

LP・コーポレートサイト

Tailwind CSS の導入は、関連記事「Tailwind CSS 使い方|v4の導入からつまずき対策まで実行結果つき」で扱っています。

よくあるエラー・つまずきと直し方

この節では、Vuetify を入れた直後に起きやすいエラーと、手元で再現したときの原文、直し方が分かります。

画面が真っ白になるエラーは、ほぼ「v-app が無い」「app.use(vuetify) が無い」の2つです。 アイコンが出ない場合はエラーが出ないため気づきにくく、Vuetify 2 の書き方は import の時点で止まります。

症状 原文(Chromium のコンソール) 原因と直し方
真っ白。v-app-bar や v-main を使っている [Vue warn]: injection "Symbol(vuetify:layout)" not found. と Error: [Vuetify] Could not find injected layout 一番外側に <v-app> が無い。App.vue の根を v-app で包む
真っ白。v-app はある injection "Symbol(vuetify:defaults)" not found. と Error: [Vuetify] Could not find defaults instance main.js で app.use(vuetify) していない
アイコンの場所が空白。エラー無し (出ない。<i class="mdi-home mdi v-icon"> は描画され、::before が none) @mdi/font の CSS(materialdesignicons.css)を import していない。または @mdi/js の別名を登録していない
Vuetify 2 の書き方を流用 SyntaxError: The requested module … does not provide an export named 'default' import { createVuetify } from 'vuetify' に書き換える
SASS 変数を設定したらビルドが落ちる Error: Preprocessor dependency "sass-embedded" not found. npm install -D sass-embedded
入力欄に「$required」と文字が出る (出ない) createRulesPlugin を app.use() していない
ルールが効かない undefined is not a valid value. Rule functions must return boolean true or a string. 引数つきの組み込みルールは ['$maxLength', 5] と配列で書く
勝手にダークになる (出ない) v4 の既定 system。theme.defaultTheme: 'light' を明示
ダイアログが背面に隠れる(開発時のみ) (公式の移行ガイドに記載) Vite の依存の事前バンドルで useStack が二重になる。optimizeDeps.include に Vuetify を足し、node_modules/.vite を消す

1SSR(Nuxt)では ssr: true

公式 FAQ は「Vue 3 は SSR を自動検出しないため、Nuxt などでは createVuetify({ ssr: true }) を手で指定する」と説明している。Nuxt では nuxt.config.ts の vite.plugins に vite-plugin-vuetify を入れ、plugins/ で登録する。

2フォントが Roboto にならない

Vuetify は Roboto を同梱しない。@fontsource/roboto を import するか、雛形どおり unplugin-fonts で読み込む。日本語は別途 Noto Sans JP などを指定する。

3Vue 3.4 以前に入らない

4.x の peerDependencies は vue ^3.5.0。npm が ERESOLVE で止まるときは、先に Vue を 3.5 以上に上げる。

Nuxt での構成そのものは、関連記事「Nuxt 4 入門|作成からビルドまで実行ログと構成図で解説」で扱っています。

よくある質問

Q. Vuetify とは何ですか? A. Vue 3 の上で動く、Material Design の見た目を持つ UI コンポーネント集です。ボタン・フォーム・表・ダイアログなど 105 種の部品を <v-btn> のようなタグで使い、テーマで色を一括して変えられます。MIT ライセンスで無料です。

Q. Vuetify の読み方は? A. 「ビューティファイ」です。Vue と beautify(美しくする)を合わせた名前です。

Q. Vuetify の使い方を最短で教えてください。 A. npm create vuetify@latest で雛形を作り、npm install → npm run dev です。既存の Vue 3 プロジェクトなら npm i vuetify @mdi/font vite-plugin-vuetify の後、createVuetify() を app.use() に渡し、App.vue の一番外側を <v-app> にします。

Q. Vuetify 3 と 4 のどちらを使えばよいですか? A. 新規は 4 です。3 は 2027年7月27日まで重大なバグとセキュリティの修正が続きますが、新しい部品は 4 に入ります。既存の 3 のアプリは、公式の移行ガイドと vuetify-codemods で移行します。

Q. Vuetify は Vue 2 で使えますか? A. Vuetify 2.7 が Vue 2 用ですが、2025年1月にサポートが終了しています。Vue 2 自体も終了済みのため、Vue 3 に移行してから Vuetify 3 以降を使います。

Q. v-app は必須ですか? A. 必須です。v-app-bar・v-navigation-drawer・v-main の位置を計算するのが v-app で、無いと手元では「[Vuetify] Could not find injected layout」で画面が真っ白になりました。

Q. アイコンが表示されません。 A. Vuetify はアイコンを同梱していません。@mdi/font を入れて materialdesignicons.css を import するか、@mdi/js と vuetify/iconsets/mdi-svg を使います。エラーは出ず、アイコンの場所が 24px の空白になります。

Q. ダークモードはどう切り替えますか? A. useTheme() の change('dark') です。v4 は既定が OS の設定に従う system なので、常にライトにしたいときは defaultTheme: 'light' を書きます。

Q. ビルドが大きいのですが減らせますか? A. vite-plugin-vuetify の autoImport で使った部品だけにし、アイコンを @mdi/js にすると、手元では受け取る量が 2.04MB → 0.76MB になりました。さらに SASS 変数で色のクラスとユーティリティを切れます。

Q. Tailwind CSS と一緒に使えますか? A. 使えますが、公式 FAQ は一般には推奨していません。併用するなら Vuetify 側の色・ユーティリティの生成を止めて、クラス名の衝突を避けます。見た目を Tailwind で付けたいなら、unstyled モードのある PrimeVue のほうが相性がよい選択です。

Q. 日本語の文言(表の件数表示など)にできますか? A. vuetify/locale の ja を locale.messages に渡し、locale: 'ja' にします。手元では表の下が「1ページあたりの件数:5」「1-5 件目 / 12件」になりました。

Q. Nuxt でも使えますか? A. 使えます。公式は nuxt.config.ts の vite.plugins に vite-plugin-vuetify を入れ、createVuetify({ ssr: true }) を Nuxt のプラグインで登録する手順を載せています。

まとめ

  • Vuetify は Vue 3 用の Material Design の UI コンポーネント集。2026年10月29日時点の最新は 4.3.1、3.x は 2027年7月27日まで LTS、2.x は終了済み。
  • 入れ方は npm i vuetify @mdi/font vite-plugin-vuetify → createVuetify() を app.use() → 一番外側を <v-app>。新規は npm create vuetify@latest。
  • 手元の社員名簿では、v-form の検証文言・v-data-table の並べ替え(文字コード順に注意)・v-dialog のフォーカス移動とスクロール停止・ダークテーマの色の入れ替わりを Chromium で確かめた。
  • ビルドは「全部登録」2.04MB → 「autoImport」1.48MB → 「autoImport+SVG アイコン」0.76MB。SASS 変数を使うとビルドが 1.5秒 → 9.2秒。
  • 真っ白の原因は v-app 無し(Could not find injected layout)か use 忘れ(Could not find defaults instance)。アイコンの空白はエラーが出ない。v4 はブレークポイント・文字クラス・影・既定テーマが v3 と違う。

Vue 側の基礎は、関連記事「Vue 3 Composition APIの使い方|早見表と実行結果」で扱っています。

参考・出典

確認日はいずれも 2026年10月29日です。

  • Vuetify「Get started with Vuetify 4 — Installation」:https://vuetifyjs.com/en/getting-started/installation/
  • Vuetify「Upgrade guide(v3 → v4)」:https://vuetifyjs.com/en/getting-started/upgrade-guide/
  • Vuetify「Browser support」:https://vuetifyjs.com/en/getting-started/browser-support/
  • Vuetify「Frequently asked questions」:https://vuetifyjs.com/en/getting-started/frequently-asked-questions/
  • Vuetify「Long-term support」:https://vuetifyjs.com/en/introduction/long-term-support/
  • Vuetify「Treeshaking」:https://vuetifyjs.com/en/features/treeshaking/
  • Vuetify「Theme」:https://vuetifyjs.com/en/features/theme/
  • Vuetify「Icon Fonts」:https://vuetifyjs.com/en/features/icon-fonts/
  • Vuetify「Display & Platform」:https://vuetifyjs.com/en/features/display-and-platform/
  • GitHub「vuetifyjs/create-vuetify」:https://github.com/vuetifyjs/create-vuetify
  • npm「vuetify」(版と公開日):https://www.npmjs.com/package/vuetify

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Vuetifyとは・使い方|v4の導入からフォーム・一覧・テーマまで実測」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ
参加受付中

AI駆動開発、 無料セミナー