Vue.js Favicon Complete Guide
Master favicon implementation in Vue.js: Vue 3, Vite, Nuxt.js, dynamic icons, composition API, and PWA integration.
Vue Favicon Quick Facts
- Location: /public folder
- Build Tool: Vite (recommended)
- Framework: Vue 3 + Composition API
- SSR: Nuxt.js support
- Dynamic: Composables & hooks
- PWA: vite-plugin-pwa
Vue 3 + Vite Setup (Recommended)
Modern Vue 3 Setup
1. File Structure
my-vue-app/
public/ ? Place all favicons here
favicon.ico
favicon-16x16.png
favicon-32x32.png
apple-touch-icon.png
android-chrome-192x192.png
android-chrome-512x512.png
site.webmanifest
src/
main.js
App.vue
index.html ? Root level
vite.config.js2. Update index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Favicons -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="theme-color" content="#42b883">
<title>Vue App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>Vite Auto-Serving: Files in
/public are served at root URL. Changes require page refresh.
Dynamic Favicon with Composition API
Vue 3 Composables
Create useFavicon Composable
// composables/useFavicon.js
import { watch, onMounted } from 'vue'
export function useFavicon(href) {
const updateFavicon = (newHref) => {
let link = document.querySelector("link[rel~='icon']")
if (!link) {
link = document.createElement('link')
link.rel = 'icon'
document.head.appendChild(link)
}
link.href = newHref
}
onMounted(() => {
if (href.value) {
updateFavicon(href.value)
}
})
watch(href, (newHref) => {
updateFavicon(newHref)
})
return { updateFavicon }
}
// Usage in component:
import { ref } from 'vue'
import { useFavicon } from './composables/useFavicon'
export default {
setup() {
const faviconPath = ref('/favicon.ico')
useFavicon(faviconPath)
const showNotification = () => {
faviconPath.value = '/favicon-notification.ico'
}
return { showNotification }
}
}Notification Badge Example
// composables/useFaviconBadge.js
import { ref, watch } from 'vue'
export function useFaviconBadge(count) {
const canvas = document.createElement('canvas')
canvas.width = 32
canvas.height = 32
const ctx = canvas.getContext('2d')
const drawBadge = (number) => {
const favicon = document.querySelector("link[rel~='icon']")
const img = new Image()
img.src = favicon?.href || '/favicon.ico'
img.onload = () => {
ctx.clearRect(0, 0, 32, 32)
ctx.drawImage(img, 0, 0, 32, 32)
if (number > 0) {
// Badge background
ctx.fillStyle = '#ff0000'
ctx.beginPath()
ctx.arc(24, 8, 8, 0, 2 * Math.PI)
ctx.fill()
// Badge text
ctx.fillStyle = '#ffffff'
ctx.font = 'bold 10px Arial'
ctx.textAlign = 'center'
ctx.fillText(number > 9 ? '9+' : number.toString(), 24, 11)
}
favicon.href = canvas.toDataURL('image/png')
}
}
watch(count, (newCount) => {
drawBadge(newCount)
})
return { drawBadge }
}
// Usage:
import { ref } from 'vue'
import { useFaviconBadge } from './composables/useFaviconBadge'
export default {
setup() {
const unreadCount = ref(0)
useFaviconBadge(unreadCount)
return { unreadCount }
}
}Nuxt.js Integration
Server-Side Rendering Support
For Nuxt.js setup, see our dedicated guide:
Nuxt.js Favicon GuideVue.js Favicon Best Practices
? Best Practices
- Place favicons in
/publicfolder - Use absolute paths (
/favicon.ico) - Create composables for reusable logic
- Use ref/reactive for dynamic updates
- Test with Vite dev server
- Include PWA manifest
- Leverage Composition API
- Verify production build
? Common Mistakes
- Placing favicons in
/src - Using relative paths
- Importing favicons in components
- Not testing production build
- Missing browser cache clear
- Forgetting theme-color meta
- Not using composables properly
- Ignoring SSR considerations
Generate Vue-Ready Favicons
Create optimized favicon packages for Vue.js applications
Generate Favicons