Кастомные иконки

Система иконок в Vuetify построена на абстракции над различными наборами иконок. Компоненты интерфейса не зависят напрямую от конкретной библиотеки — вместо этого используется единый механизм рендеринга иконок, который может работать с Material Design Icons, Font Awesome, SVG-иконками, иконками из файлов, а также с полностью кастомными компонентами.

Базовым элементом системы является компонент v-icon, который отвечает за отображение иконок в интерфейсе. Он используется напрямую или внутри других компонентов:

  • v-btn
  • v-list-item
  • v-navigation-drawer
  • v-text-field
  • v-tabs
  • v-chip
  • v-toolbar

Vuetify предоставляет механизм регистрации кастомных иконок, позволяющий:

  • подключать собственные SVG-иконки
  • заменять стандартные иконки фреймворка
  • объединять разные наборы иконок
  • создавать иконки как Vue-компоненты

Компонент v-icon

Компонент v-icon является универсальным контейнером для отображения иконок.

Простейшее использование:

<v-icon>mdi-home</v-icon>

Vuetify определяет активный набор иконок и отображает нужный символ.

Возможные варианты:

<v-icon icon="mdi-account"></v-icon>

<v-icon size="24">
  mdi-settings
</v-icon>

<v-icon color="red">
  mdi-alert
</v-icon>

Основные свойства компонента:

Свойство Описание
icon имя иконки
size размер иконки
color цвет
start / end позиционирование внутри компонентов
tag HTML-тег контейнера

Пример с кнопкой:

<v-btn>
  <v-icon start>mdi-plus</v-icon>
  Добавить
</v-btn>

Настройка системы иконок

В Vuetify 3 настройка иконок выполняется при создании экземпляра фреймворка.

import { createVuetify } from 'vuetify'

export default createVuetify({
  icons: {
    defaultSet: 'mdi'
  }
})

Параметр icons содержит:

Параметр Назначение
defaultSet основной набор иконок
sets зарегистрированные наборы
aliases псевдонимы иконок

Aliases (псевдонимы иконок)

Vuetify активно использует aliases — имена-псевдонимы для иконок, используемых внутри компонентов.

Например:

  • close
  • menu
  • success
  • error
  • prev
  • next

Alias связывает внутреннее имя Vuetify с конкретной иконкой.

Пример настройки:

import { aliases } from 'vuetify/iconsets/mdi'

createVuetify({
  icons: {
    defaultSet: 'mdi',
    aliases
  }
})

Кастомный alias:

createVuetify({
  icons: {
    aliases: {
      dashboard: 'mdi-view-dashboard'
    }
  }
})

Использование:

<v-icon icon="dashboard"></v-icon>

Подключение собственного набора иконок

Vuetify позволяет регистрировать собственные наборы.

Структура набора:

const customSet = {
  component: (props) => h(...)
}

Регистрация:

createVuetify({
  icons: {
    defaultSet: 'custom',
    sets: {
      custom: customSet
    }
  }
})

После регистрации:

<v-icon icon="custom:home"></v-icon>

Префикс указывает Vuetify использовать конкретный набор.


Кастомные SVG-иконки

Наиболее распространённый способ создания собственных иконок — использование SVG.

SVG можно встроить прямо в компонент.

Создание SVG-иконки

import { h } from 'vue'

const MyIcon = {
  component: (props) => {
    return h(
      'svg',
      {
        viewBox: '0 0 24 24',
        width: props.size,
        height: props.size
      },
      [
        h('path', {
          d: 'M12 2L2 7h20L12 2z'
        })
      ]
    )
  }
}

Регистрация:

createVuetify({
  icons: {
    sets: {
      custom: {
        component: MyIcon
      }
    }
  }
})

Использование:

<v-icon icon="custom"></v-icon>

Использование Vue-компонентов как иконок

Vuetify поддерживает регистрацию Vue-компонентов в качестве иконок.

Создание компонента:

// icons/StarIcon.vue

<template>
<svg viewBox="0 0 24 24">
  <path d="M12 2L15 9H22L17 13L19 21L12 17L5 21L7 13L2 9H9Z"/>
</svg>
</template>

Регистрация:

import StarIcon from '@/icons/StarIcon.vue'

createVuetify({
  icons: {
    aliases: {
      star: StarIcon
    }
  }
})

Использование:

<v-icon icon="star"></v-icon>

Использование SVG-файлов

Иконки можно импортировать напрямую из SVG-файлов.

import MyIcon from '@/assets/icons/custom.svg'

Регистрация:

createVuetify({
  icons: {
    aliases: {
      customIcon: MyIcon
    }
  }
})

Использование:

<v-icon icon="customIcon"></v-icon>

Такой подход требует соответствующей конфигурации сборщика (Vite / Webpack).


Замена встроенных иконок Vuetify

Компоненты Vuetify используют alias-иконки. Их можно заменить.

Пример: замена иконки закрытия.

createVuetify({
  icons: {
    aliases: {
      close: 'mdi-close-circle'
    }
  }
})

Теперь все компоненты будут использовать новую иконку:

  • v-dialog
  • v-snackbar
  • v-chip

Создание полноценного кастомного набора

Иногда требуется создать целую библиотеку иконок.

Структура

icons/
  home.svg
  user.svg
  settings.svg

Создание набора:

import HomeIcon from '@/icons/home.svg'
import UserIcon from '@/icons/user.svg'
import SettingsIcon from '@/icons/settings.svg'

const customIcons = {
  home: HomeIcon,
  user: UserIcon,
  settings: SettingsIcon
}

Регистрация:

createVuetify({
  icons: {
    defaultSet: 'custom',
    sets: {
      custom: {
        component: (props) => {
          const Icon = customIcons[props.icon]
          return h(Icon)
        }
      }
    }
  }
})

Использование:

<v-icon icon="home"></v-icon>
<v-icon icon="user"></v-icon>

Глобальная библиотека иконок

Для крупных проектов удобно создать централизованный файл иконок.

src/icons/index.js
import Dashboard from './dashboard.svg'
import User from './user.svg'
import Settings from './settings.svg'

export default {
  dashboard: Dashboard,
  user: User,
  settings: Settings
}

Подключение:

import icons from '@/icons'

createVuetify({
  icons: {
    aliases: icons
  }
})

Это позволяет:

  • централизовать управление иконками
  • избегать дублирования
  • упростить масштабирование проекта

Динамический выбор иконок

Иконку можно выбирать динамически.

<v-icon :icon="currentIcon"></v-icon>
const currentIcon = ref('mdi-home')

Изменение значения:

currentIcon.value = 'mdi-account'

Условный рендеринг иконок

<v-icon v-if="isOpen">
  mdi-chevron-up
</v-icon>

<v-icon v-else>
  mdi-chevron-down
</v-icon>

Или:

<v-icon :icon="isOpen ? 'mdi-eye' : 'mdi-eye-off'"></v-icon>

Стилизация кастомных иконок

Иконки можно стилизовать через CSS.

<v-icon class="custom-icon">
  mdi-heart
</v-icon>
.custom-icon {
  font-size: 32px;
  color: #ff4081;
}

SVG-иконки поддерживают:

  • fill
  • stroke
  • opacity

Пример:

svg {
  fill: currentColor;
}

Использование currentColor позволяет иконке автоматически наследовать цвет текста.


Производительность и оптимизация

При использовании кастомных иконок важно учитывать производительность.

Основные рекомендации:

Использование SVG вместо шрифтов

SVG:

  • лучше масштабируется
  • не зависит от загрузки шрифта
  • легче оптимизируется

Tree-shaking

Импорт только используемых иконок:

import { mdiAccount } from '@mdi/js'

Lazy loading

Для больших наборов иконок можно применять динамический импорт:

const icon = await import(`@/icons/${name}.svg`)

Практический пример интеграции

Полная настройка кастомных иконок:

import { createVuetify } from 'vuetify'
import DashboardIcon from '@/icons/dashboard.svg'
import UserIcon from '@/icons/user.svg'

const aliases = {
  dashboard: DashboardIcon,
  user: UserIcon
}

export default createVuetify({
  icons: {
    defaultSet: 'custom',
    aliases
  }
})

Использование в интерфейсе:

<v-btn>
  <v-icon start icon="dashboard"></v-icon>
  Панель
</v-btn>

<v-list-item>
  <v-icon start icon="user"></v-icon>
  Профиль
</v-list-item>

Типичные ошибки при работе с кастомными иконками

Неправильный размер SVG

SVG должен иметь корректный viewBox.

Правильно:

<svg viewBox="0 0 24 24">

Без viewBox масштабирование работать не будет.


Отсутствие currentColor

Если SVG содержит фиксированный цвет:

fill="#000"

иконка не будет менять цвет через Vuetify.

Правильно:

fill="currentColor"

Конфликт наборов иконок

Если используется несколько наборов:

<v-icon icon="mdi:home"></v-icon>
<v-icon icon="fa:user"></v-icon>

нужно явно указывать префикс.


Неоптимизированные SVG

SVG-иконки часто содержат лишние данные:

  • metadata
  • comments
  • лишние группы

Оптимизация выполняется через SVGO.


Организация иконок в больших проектах

Рекомендуемая структура:

src/
  icons/
    navigation/
    actions/
    status/
    index.js

Это позволяет:

  • логически разделить иконки
  • упростить поиск
  • снизить вероятность конфликтов имен

Использование иконок внутри кастомных компонентов

Иконки можно инкапсулировать внутри компонентов.

<template>
<v-btn>
  <v-icon start icon="mdi-download"/>
  Скачать
</v-btn>
</template>

Компонент становится переиспользуемым:

DownloadButton.vue

Такой подход:

  • уменьшает дублирование
  • стандартизирует интерфейс
  • упрощает поддержку проекта