How to Change the Favicon in Vue 3 (Static & Dynamic)
If you've ever shipped a Vue application only to realize the browser tab still displays that default green 'V' logo, you've missed a small but vital branding step. It's the digital equivalent of wearing a tailored suit with mismatched socks. In 2026, users expect a polished experience from the moment the tab starts loading, and a generic icon screams 'unfinished project'.
This guide is about Vue itself. For the general Vite favicon setup (public folder, link tags, build output), see our main Vite favicon guide.
Most developers struggle with Vue favicon setup because they try to treat the icon like a standard Vue component or a bundled asset. That's a mistake. Favicons live outside the standard component lifecycle and require a specific strategy to work across Safari, Chrome, and mobile home screens. We're going to fix that today using the modern Vite-based workflow.
The 'Public' Strategy: Why It Wins
In a modern Vue 3 project powered by Vite, you have two main places to store images: the src/assets folder and the public folder. For your favicon, the public directory is the only correct choice. Why? Because Vite doesn't process files in the public folder; it simply copies them to the root of your dist folder during the build process.
When the browser looks for /favicon.ico, it expects it at the root. If you put your icon in src/assets, Vite will hash the filename (e.g., favicon.a1b2c3.ico), and the browser won't find it unless you manually import it into every page. Stick to the public folder to keep your life simple and your paths predictable.
Step 1: Preparing Your Assets
Don't just settle for a single .ico file. In 2026, the gold standard is a combination of SVG for modern browsers and a legacy ICO fallback. SVG allows for crisp scaling and even dark mode support. You can use SVG favicons to ensure your logo looks sharp on 5K displays without adding bulk to your bundle.
You should have three files ready in your public folder:
favicon.ico (The 32x32 fallback)
favicon.svg (The modern scalable icon)
apple-touch-icon.png (180x180 for iOS users)
Step 2: Updating the Entry Point
Since Vue is a Single Page Application (SPA), you only need to edit one file: index.html. This file sits at the root of your project. Open it and look for the <head> section. You'll want to replace the default boilerplate with this specific sequence:
This order matters. Modern browsers will see the SVG and prefer it because of the type='image/svg+xml' attribute, while older browsers will ignore it and grab the ICO file. If your icon isn't updating after this change, you likely need to perform a favicon cache clear to force the browser to recognize the new files.
Step 3: Dynamic Favicons for Notifications
One of the coolest things about Vue is reactivity. You can actually change your favicon based on the state of your app. Think about how GitHub adds a small blue dot to their favicon when you have unread notifications. You can achieve this in Vue by creating a simple utility function.
export function setDynamicFavicon(iconPath) {
const link = document.querySelector("link[rel*='icon']");
if (link) {
link.href = iconPath;
}
}
You can call this function inside a watch effect in your App.vue. For example, if a user has unread messages, you swap /favicon.svg for /favicon-notification.svg. It's a tiny detail that makes your web app feel like a native desktop application.
Common Pitfalls to Avoid
The most frequent error I see is using relative paths like ./favicon.ico. In a Vue Router setup with nested paths (like /user/settings/profile), a relative path will break because the browser will look for the icon at /user/settings/favicon.ico. Always use absolute paths starting with a forward slash (/favicon.ico).
Another trap is ignoring the manifest file. If you want your Vue app to look professional when 'Added to Home Screen' on Android, you need a manifest.json in your public folder that points to your icons. Without it, Android will just show a generic screenshot of your site, which looks amateur.
At the end of the day, your favicon is your brand's smallest ambassador. Setting it up correctly in Vue takes less than five minutes but pays off every time a user looks at their crowded browser tabs. Keep it simple, use the public folder, and always provide an SVG version for the best results in 2026.
Si alguna vez has desplegado una aplicación Vue solo para darte cuenta de que la pestaña del navegador todavía muestra el logotipo verde 'V' por defecto, te has saltado un paso de branding pequeño pero vital. Es el equivalente digital a llevar un traje a medida con calcetines desparejados. En 2026, los usuarios esperan una experiencia pulida desde el momento en que la pestaña comienza a cargarse, y un icono genérico grita 'proyecto inacabado'.
La mayoría de los desarrolladores tienen problemas con el vue favicon setup porque intentan tratar el icono como un componente estándar de Vue o un recurso empaquetado. Eso es un error. Los favicons viven fuera del ciclo de vida estándar de los componentes y requieren una estrategia específica para funcionar en Safari, Chrome y pantallas de inicio móviles. Vamos a solucionar eso hoy usando el flujo de trabajo moderno basado en Vite.
La estrategia 'Public': Por qué es la ganadora
En un proyecto moderno de Vue 3 impulsado por Vite, tienes dos lugares principales para almacenar imágenes: la carpeta src/assets y la carpeta public. Para tu favicon, el directorio public es la única opción correcta. ¿Por qué? Porque Vite no procesa los archivos en la carpeta public; simplemente los copia a la raíz de tu carpeta dist durante el proceso de construcción.
Cuando el navegador busca /favicon.ico, espera encontrarlo en la raíz. Si pones tu icono en src/assets, Vite aplicará un hash al nombre del archivo (ej. favicon.a1b2c3.ico), y el navegador no lo encontrará a menos que lo importes manualmente en cada página. Quédate con la carpeta public para mantener tu vida simple y tus rutas predecibles.
Paso 1: Preparando tus recursos
No te conformes solo con un archivo .ico. En 2026, el estándar de oro es una combinación de SVG para navegadores modernos y un fallback ICO para los antiguos. El SVG permite un escalado nítido e incluso soporte para modo oscuro. Puedes usar favicons SVG para asegurar que tu logo se vea perfecto en pantallas 5K sin aumentar el tamaño de tu bundle.
Deberías tener tres archivos listos en tu carpeta public:
favicon.ico (El fallback de 32x32)
favicon.svg (El icono vectorial moderno)
apple-touch-icon.png (180x180 para usuarios de iOS)
Paso 2: Actualizando el punto de entrada
Como Vue es una Single Page Application (SPA), solo necesitas editar un archivo: index.html. Este archivo se encuentra en la raíz de tu proyecto. Ábrelo y busca la sección <head>. Querrás reemplazar el código por defecto con esta secuencia específica:
Este orden importa. Los navegadores modernos verán el SVG y lo preferirán por el atributo type='image/svg+xml', mientras que los navegadores antiguos lo ignorarán y tomarán el archivo ICO. Si tu icono no se actualiza, es probable que necesites realizar una limpieza de caché del favicon para forzar al navegador a reconocer los nuevos archivos.
Paso 3: Favicons dinámicos para notificaciones
Una de las cosas más geniales de Vue es la reactividad. Puedes cambiar tu favicon basándote en el estado de tu app. Piensa en cómo GitHub añade un pequeño punto azul a su favicon cuando tienes notificaciones sin leer. Puedes lograr esto en Vue creando una función de utilidad simple.
export function setDynamicFavicon(iconPath) {
const link = document.querySelector("link[rel*='icon']");
if (link) {
link.href = iconPath;
}
}
Puedes llamar a esta función dentro de un watch en tu App.vue. Por ejemplo, si un usuario tiene mensajes sin leer, cambias /favicon.svg por /favicon-notification.svg. Es un detalle minúsculo que hace que tu web app se sienta como una aplicación de escritorio nativa.
Errores comunes a evitar
El error más frecuente que veo es usar rutas relativas como ./favicon.ico. En una configuración de Vue Router con rutas anidadas (como /user/settings/profile), una ruta relativa fallará porque el navegador buscará el icono en /user/settings/favicon.ico. Usa siempre rutas absolutas que comiencen con una barra diagonal (/favicon.ico).
Otra trampa es ignorar el archivo manifest. Si quieres que tu aplicación Vue parezca profesional cuando se 'Añade a la pantalla de inicio' en Android, necesitas un manifest.json en tu carpeta public que apunte a tus iconos. Sin él, Android mostrará una captura de pantalla genérica de tu sitio, lo cual se ve poco profesional.
Al final del día, tu favicon es el embajador más pequeño de tu marca. Configurarlo correctamente en Vue toma menos de cinco minutos pero rinde frutos cada vez que un usuario mira sus pestañas abarrotadas. Mantenlo simple, usa la carpeta public y siempre proporciona una versión SVG para los mejores resultados en 2026.
Vue 애플리케이션을 배포한 후 브라우저 탭에 여전히 기본 녹색 'V' 로고가 표시되고 있다면, 브랜딩의 작지만 중요한 단계를 놓친 것입니다. 이는 마치 맞춤 정장을 입고 짝짝이 양말을 신은 것과 같습니다. 2026년의 사용자들은 탭이 로딩되는 순간부터 세련된 경험을 기대하며, 일반적인 아이콘은 '미완성 프로젝트'라는 인상을 줍니다.
많은 개발자들이 Vue favicon setup 과정에서 어려움을 겪는 이유는 아이콘을 표준 Vue 컴포넌트나 번들된 에셋처럼 취급하려 하기 때문입니다. 그것은 실수입니다. 파비콘은 표준 컴포넌트 생명주기 외부에 존재하며, Safari, Chrome 및 모바일 홈 화면에서 제대로 작동하려면 특정 전략이 필요합니다. 오늘은 Vite 기반의 현대적인 워크플로우를 사용하여 이 문제를 해결해 보겠습니다.
'Public' 폴더 전략: 왜 이것이 정답인가
Vite로 구동되는 현대적인 Vue 3 프로젝트에는 이미지를 저장할 수 있는 두 가지 주요 위치가 있습니다: src/assets 폴더와 public 폴더입니다. 파비콘의 경우 public 디렉토리가 유일하고 올바른 선택입니다. 왜 그럴까요? Vite는 public 폴더의 파일을 처리하지 않고 빌드 중에 dist 폴더의 루트로 그대로 복사하기 때문입니다.
브라우저가 /favicon.ico를 찾을 때 루트 디렉토리에서 찾을 것을 기대합니다. 아이콘을 src/assets에 넣으면 Vite가 파일 이름을 해싱(예: favicon.a1b2c3.ico)하게 되어, 모든 페이지에서 수동으로 임포트하지 않는 한 브라우저가 찾을 수 없게 됩니다. 경로를 예측 가능하게 유지하려면 public 폴더를 고수하세요.
1단계: 에셋 준비하기
단순히 .ico 파일 하나에 만족하지 마세요. 2026년의 표준은 최신 브라우저를 위한 SVG와 레거시를 위한 ICO 폴백의 조합입니다. SVG는 선명한 스케일링을 가능하게 하며 다크 모드까지 지원합니다. SVG 파비콘 가이드를 참고하여 5K 디스플레이에서도 선명하게 보이는 아이콘을 준비하세요.
public 폴더에 다음 세 가지 파일을 준비해야 합니다:
favicon.ico (32x32 폴백용)
favicon.svg (최신 벡터 아이콘)
apple-touch-icon.png (iOS 사용자용, 180x180)
2단계: index.html 업데이트
Vue는 싱글 페이지 애플리케이션(SPA)이므로 index.html 파일 하나만 수정하면 됩니다. 프로젝트 루트에 있는 이 파일을 열고 <head> 섹션을 찾으세요. 기본 코드를 다음 시퀀스로 교체하십시오:
이 순서가 중요합니다. 최신 브라우저는 type='image/svg+xml' 속성을 보고 SVG를 우선적으로 사용하며, 구형 브라우저는 이를 무시하고 ICO 파일을 가져옵니다. 변경 후에도 아이콘이 업데이트되지 않는다면 파비콘 캐시 삭제를 통해 브라우저가 새 파일을 인식하도록 강제해야 합니다.
3단계: 동적 알림 파비콘 구현
Vue의 가장 멋진 기능 중 하나는 반응성입니다. 앱의 상태에 따라 파비콘을 동적으로 변경할 수 있습니다. GitHub가 읽지 않은 알림이 있을 때 파비콘에 작은 파란색 점을 추가하는 방식을 생각해 보세요. Vue에서도 간단한 유틸리티 함수로 이를 구현할 수 있습니다.
export function setDynamicFavicon(iconPath) {
const link = document.querySelector("link[rel*='icon']");
if (link) {
link.href = iconPath;
}
}
이 함수를 App.vue의 watch 내에서 호출할 수 있습니다. 예를 들어 읽지 않은 메시지가 있을 때 /favicon.svg를 /favicon-notification.svg로 교체하면 웹 앱이 마치 네이티브 데스크톱 앱처럼 느껴지게 됩니다.
주의해야 할 일반적인 실수
가장 자주 보이는 실수는 ./favicon.ico와 같은 상대 경로를 사용하는 것입니다. /user/settings/profile과 같이 중첩된 경로가 있는 Vue Router 설정에서 상대 경로는 브라우저가 /user/settings/favicon.ico에서 아이콘을 찾게 만들어 오류를 발생시킵니다. 항상 슬래시로 시작하는 절대 경로(/favicon.ico)를 사용하세요.
또한 안드로이드의 '홈 화면에 추가' 기능을 고려한다면 manifest.json을 잊지 마세요. 이것이 없으면 안드로이드는 사이트의 일반적인 스크린샷을 아이콘으로 표시하게 되어 매우 비전문적으로 보입니다.
결국 파비콘은 브랜드의 가장 작은 대사입니다. Vue에서 이를 올바르게 설정하는 데는 5분도 걸리지 않지만, 사용자가 붐비는 브라우저 탭을 볼 때마다 그 가치를 발휘합니다. 단순함을 유지하고 public 폴더를 활용하며, 2026년 최고의 결과를 위해 항상 SVG 버전을 제공하세요.
在由 Vite 驱动的现代 Vue 3 项目中,你有两个主要地方可以存放图片:src/assets 文件夹和 public 文件夹。对于 Favicon,public 目录是唯一正确的选择。为什么?因为 Vite 不会处理 public 文件夹中的文件;它只是在构建过程中将它们原封不动地复制到 dist 文件夹的根目录。
当浏览器寻找 /favicon.ico 时,它期望在根目录下找到它。如果你把图标放在 src/assets 中,Vite 会对文件名进行哈希处理(例如 favicon.a1b2c3.ico),除非你手动在每个页面中导入它,否则浏览器将无法找到它。坚持使用 public 文件夹,让你的路径保持简单且可预测。