Saltar al contenido
favicon-e-iconos.html · devschool

Favicon e iconos en HTML

Lección 27 de 39 · 13 min de lectura · Actualizado el

En esta lección
  1. Dónde aparece el icono de tu web
  2. El clásico favicon.ico
  3. El favicon en SVG
  4. El icono para iPhone: apple-touch-icon
  5. Webs instalables: el manifest
  6. El conjunto recomendado
  7. Iconos dentro de la página
  8. Iconos accesibles
  9. Errores frecuentes
  10. Resumen

El favicon es el pequeño icono que aparece en la pestaña del navegador junto al título de tu página. Parece un detalle menor, pero es lo que ayuda a reconocer tu web entre veinte pestañas abiertas, en los marcadores y en el historial. En esta lección aprenderás qué archivos de icono necesita hoy una web y cómo enlazarlos, qué es el apple-touch-icon, cómo escribir un manifest para que tu web se pueda instalar en el móvil como si fuera una app, y cómo usar iconos SVG dentro de tus páginas (en línea y con sprites) sin olvidar la accesibilidad.

Dónde aparece el icono de tu web

El mismo logotipo, en distintos tamaños, se muestra en muchos sitios:

  • En la pestaña del navegador y en la barra de marcadores (16 × 16 o 32 × 32 píxeles).
  • En los resultados de Google en el móvil, junto al nombre de la web.
  • En la pantalla de inicio del móvil, si alguien añade tu web como acceso directo (180 × 180 en iPhone, 192 × 192 o más en Android).
  • En la lista de aplicaciones del ordenador o del móvil, si la web se instala como app (512 × 512).

Por eso no basta con una sola imagen: cada sitio pide un tamaño y, a veces, un formato distinto. La buena noticia es que con cuatro o cinco archivos cubres todos los casos.

El clásico favicon.ico

Históricamente, el favicon era un archivo llamado favicon.ico en la raíz de la web. El formato ICO es un contenedor de Windows que puede guardar varios tamaños dentro del mismo archivo.

Todos los navegadores, si no encuentran ningún <link rel="icon"> en tu página, piden automáticamente /favicon.ico a tu servidor. Si no existe, verás en la pestaña Red de las DevTools una petición con error 404, y en la pestaña un icono genérico.

Hoy se sigue recomendando tener un favicon.ico de 32 × 32 en la raíz, por dos motivos: lo usan programas que no leen tu HTML (lectores de noticias, algunos clientes de correo) y evita ese 404.

<link rel="icon" href="/favicon.ico" sizes="32x32">

El atributo sizes indica el tamaño del icono. Aquí sirve para que los navegadores modernos prefieran el SVG que añadirás a continuación.

El favicon en SVG

Todos los navegadores actuales aceptan un favicon en SVG. Tiene dos ventajas enormes: se ve nítido a cualquier tamaño (es vectorial) y, como un SVG puede llevar CSS dentro, puede cambiar de color en modo oscuro.

<link rel="icon" href="/icon.svg" type="image/svg+xml">

Y este podría ser el archivo icon.svg de un club de montaña:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    path { fill: #1d3557; }
    @media (prefers-color-scheme: dark) {
      path { fill: #f1faee; }
    }
  </style>
  <path d="M2 28 L12 10 L17 18 L21 12 L30 28 Z" />
</svg>

Con el tema claro del sistema, la montaña es azul oscuro; con el tema oscuro, casi blanca, para que no desaparezca sobre una pestaña negra. Fíjate en que el archivo SVG suelto necesita el atributo xmlns; dentro del HTML no hace falta. Lo básico de SVG lo tienes en SVG y canvas.

Consejo: diseña el favicon pensando en 16 píxeles. Un logotipo con texto o muchos detalles se convierte en una mancha. Usa solo el símbolo, o la inicial de la marca, con formas grandes y buen contraste.

El icono para iPhone: apple-touch-icon

Cuando alguien usa “Añadir a pantalla de inicio” en Safari, el iPhone no usa el favicon: busca un apple-touch-icon, una imagen PNG de 180 × 180 píxeles.

<link rel="apple-touch-icon" href="/apple-touch-icon.png">

Tres detalles de este icono:

  • Sin transparencia. iOS rellena las zonas transparentes de negro. Pon un fondo de color.
  • Con margen. iOS redondea las esquinas automáticamente; deja unos 20 píxeles de margen alrededor del dibujo para que no se recorte.
  • Si lo guardas como /apple-touch-icon.png en la raíz, Safari lo encuentra aunque no lo enlaces. Enlázalo igualmente: es más claro.

Webs instalables: el manifest

Una PWA (Progressive Web App, aplicación web progresiva) es una web que se puede instalar en el móvil o el ordenador: tiene su propio icono en la pantalla de inicio, se abre en una ventana sin la barra del navegador y puede funcionar sin conexión. Para todo eso no hace falta una tienda de aplicaciones.

La pieza básica es el manifest: un archivo JSON que describe la aplicación. Se enlaza desde el <head>:

<link rel="manifest" href="/manifest.webmanifest">

Y este es un manifest mínimo para la web de un gimnasio:

{
  "name": "Gimnasio Atlas · Reservas",
  "short_name": "Atlas",
  "description": "Reserva tus clases de spinning, pilates y yoga.",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#1d3557",
  "lang": "es",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
    { "src": "/icon-mask.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
  ]
}
PropiedadPara qué sirve
nameNombre completo, en la pantalla de instalación
short_nameNombre corto, bajo el icono (unos 12 caracteres)
start_urlPágina que se abre al lanzar la app
displaystandalone: ventana propia sin barra del navegador; browser: como una web normal
background_colorColor de la pantalla de carga mientras se abre
theme_colorColor de la barra de estado; ponlo igual que el <meta name="theme-color">
iconsLos iconos, como mínimo de 192 y 512 píxeles

El JSON es estricto: comillas dobles en todas las claves y valores de texto, y sin coma después del último elemento. Una coma de más y el navegador ignora el manifest entero. Tienes las reglas en la lección de JSON.

Iconos maskable

Android recorta los iconos con la forma que elija cada fabricante: círculo, cuadrado redondeado, gota… Un icono marcado con "purpose": "maskable" está preparado para ese recorte: el dibujo ocupa solo el círculo central (aproximadamente el 80 % del lado) y el resto es fondo de color. Si no das uno, Android puede meter tu icono pequeño dentro de un círculo blanco.

¿Y el funcionamiento sin conexión?

El manifest hace la web instalable, pero no hace que funcione sin Internet. Para eso hace falta un service worker, un archivo de JavaScript que intercepta las peticiones y puede responder con copias guardadas. Es un tema de JavaScript avanzado; de momento quédate con la idea: manifest + iconos + HTTPS es la base de cualquier PWA, y algunos navegadores piden además un service worker para ofrecer el botón de instalar.

En las DevTools de Chrome, pestaña Aplicación → Manifiesto, puedes ver si el navegador lee bien tu manifest, qué iconos encuentra y qué le falta para ser instalable.

El conjunto recomendado

Juntándolo todo, esto es lo que necesita hoy una web en su <head>:

<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.webmanifest">
<meta name="theme-color" content="#1d3557">

Y estos archivos en la raíz:

mi-web/
├── favicon.ico            (32 × 32)
├── icon.svg               (vectorial, con modo oscuro)
├── apple-touch-icon.png   (180 × 180, sin transparencia)
├── icon-192.png
├── icon-512.png
├── icon-mask.png          (512 × 512, maskable)
└── manifest.webmanifest

No necesitas las decenas de tamaños (favicon-57x57.png, favicon-72x72.png…) que verás en plantillas antiguas: eran para dispositivos que ya no existen.

Nota: para crear todos estos archivos a partir de tu logo hay generadores en línea gratuitos (busca “favicon generator”). Súbeles un SVG o un PNG grande, revisa el resultado y copia solo las líneas que necesites.

“He cambiado el favicon y no se actualiza”

Los navegadores guardan el favicon en caché con mucha insistencia. Si lo cambias y sigues viendo el antiguo, prueba a abrir la página en una ventana de incógnito o a recargar forzando (Ctrl + F5). En la web publicada puedes añadir un parámetro para que se trate como un archivo nuevo: href="/icon.svg?v=2".

Iconos dentro de la página

Además del favicon, casi todas las webs usan iconos en su contenido: una lupa en el buscador, un teléfono junto al número de contacto, tres rayas para abrir el menú. Hay varias formas de ponerlos:

FormaVentajasInconvenientes
<img src="lupa.svg">Sencillo, se guarda en cachéNo cambia de color con el CSS
SVG en líneaColor con currentColor, animableRepetir el mismo <svg> engorda el HTML
Sprite SVG con <use>Se define una vez y se reutilizaUn poco más de preparación
Fuente de iconosMuy usada antesPeor accesibilidad y carga; evítala en proyectos nuevos
EmojiCero archivosCada sistema los dibuja distinto

SVG en línea con currentColor

Si escribes stroke="currentColor" o fill="currentColor", el icono toma el color del texto que lo rodea. Así, al pasar el ratón por un enlace que cambia de color, el icono cambia con él sin tocar nada más.

<a href="tel:+34942000000" class="contacto">
  <svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"
       fill="none" stroke="currentColor" stroke-width="2">
    <rect x="7" y="2" width="10" height="20" rx="2" />
    <line x1="11" y1="18" x2="13" y2="18" />
  </svg>
  942 00 00 00
</a>

Sprites: define una vez, usa muchas

Un sprite es un único SVG que contiene varios iconos, cada uno dentro de un <symbol> con su id. El sprite no se muestra; luego, cada vez que necesitas un icono, lo “llamas” con <use>:

<!-- Al principio del body: el almacén de iconos, oculto -->
<svg hidden>
  <symbol id="i-lupa" viewBox="0 0 24 24">
    <circle cx="10" cy="10" r="6" />
    <line x1="15" y1="15" x2="21" y2="21" />
  </symbol>
  <symbol id="i-menu" viewBox="0 0 24 24">
    <path d="M3 6 H21 M3 12 H21 M3 18 H21" />
  </symbol>
</svg>

<!-- Donde quieras usarlos -->
<svg class="icono" aria-hidden="true"><use href="#i-lupa"></use></svg>
<svg class="icono" aria-hidden="true"><use href="#i-menu"></use></svg>
.icono {
  width: 1.2em;
  height: 1.2em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}

Cada <symbol> lleva su propio viewBox, así que el <svg> que lo usa no lo necesita. Con width y height en em, el icono crece con el tamaño de letra. Pruébalo en el editor de esta lección.

El sprite también puede ser un archivo aparte, iconos.svg, y entonces se llama así: <use href="/img/iconos.svg#i-lupa">. El navegador lo descarga una vez y lo guarda en caché para todas las páginas. Debe estar en tu mismo dominio: un sprite de otro dominio no se carga.

Nota: en código antiguo verás xlink:href en lugar de href. Era la sintaxis de SVG 1.1; hoy basta con href.

Iconos accesibles

Un lector de pantalla no “ve” un icono: solo puede anunciar lo que tú le digas. Hay dos situaciones, y cada una tiene su solución (ya las viste por encima en SVG y canvas):

1. El icono acompaña a un texto que ya lo dice todo (“Inicio”, “Buscar”, el número de teléfono). Es decorativo: ocúltalo con aria-hidden="true" para que no se anuncie dos veces ni se lea como “imagen sin nombre”.

2. El icono va solo, sin texto visible. Entonces es lo único que explica para qué sirve el botón o el enlace, y necesita un nombre accesible. La forma más simple es aria-label en el botón:

<button type="button" aria-label="Cerrar aviso">
  <svg class="icono" aria-hidden="true"><use href="#i-cerrar"></use></svg>
</button>

Otra opción es un texto real que se oculta visualmente con CSS pero que los lectores sí leen (la clase suele llamarse visualmente-oculto o sr-only; la verás en CSS accesible):

<a href="/carrito/">
  <svg class="icono" aria-hidden="true"><use href="#i-carrito"></use></svg>
  <span class="visualmente-oculto">Carrito (3 productos)</span>
</a>

Algunas reglas más:

  • El nombre describe la acción, no el dibujo: “Buscar”, no “Lupa”; “Abrir menú”, no “Tres rayas”.
  • Si el icono es una imagen <img>, el texto va en su alt: alt="Buscar" si va solo, alt="" si es decorativo.
  • Un botón solo con icono debe tener un tamaño cómodo para el dedo: unos 44 × 44 píxeles de zona pulsable, aunque el dibujo sea más pequeño.
  • Los iconos que transmiten un estado (un aviso rojo, un check verde) no deben depender solo del color.

Todo lo relativo a ARIA se amplía en ARIA a fondo.

Errores frecuentes

  • No tener ningún favicon: el navegador pide /favicon.ico, recibe un 404 y la pestaña muestra un icono genérico.
  • Usar el logotipo completo, con texto, como favicon: a 16 píxeles es ilegible. Usa un símbolo sencillo.
  • apple-touch-icon con fondo transparente: en el iPhone aparece con fondo negro.
  • Una coma de más en el manifest: el JSON deja de ser válido y el navegador lo ignora sin avisar en la página. Revísalo en DevTools → Aplicación.
  • Rutas relativas que fallan en subcarpetas: href="favicon.ico" funciona en la portada, pero no en /blog/articulo.html. Usa rutas absolutas desde la raíz (/favicon.ico).
  • Botones solo con icono y sin nombre: el lector anuncia simplemente “botón”. Añade aria-label o un texto oculto.
  • Olvidar aria-hidden="true" en iconos decorativos: el lector los anuncia como imágenes sin nombre o repite la información.
  • Usar un sprite de otro dominio con <use>: no se carga por seguridad; sírvelo desde tu web.

Resumen

Archivo o técnicaPara quéCómo
favicon.icoCompatibilidad y evitar el 40432 × 32 en la raíz, sizes="32x32"
icon.svgFavicon nítido y con modo oscurotype="image/svg+xml", @media (prefers-color-scheme)
apple-touch-icon.pngPantalla de inicio del iPhone180 × 180, fondo opaco
manifest.webmanifestWeb instalable (PWA)JSON con nombre, colores e iconos 192 y 512
Icono maskableRecorte de AndroidDibujo en el 80 % central
SVG en líneaIconos que siguen el color del textocurrentColor
SpriteReutilizar iconos<symbol id> + <use href="#id">
AccesibilidadQue el icono se entiendaaria-hidden si decora, aria-label si va solo

En la siguiente lección verás cómo preparar tu HTML para que los buscadores entiendan y muestren bien tus páginas: SEO en HTML.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

favicon-e-iconos.html
Resultado

Pon a prueba lo que has aprendido

[HTML] ¿Por qué tiene ventaja un favicon en SVG frente a uno PNG?

[HTML] Tu apple-touch-icon tiene el fondo transparente. ¿Qué pasará al añadir la web a la pantalla de inicio del iPhone?

[HTML] ¿Por qué el navegador ignora este manifest?
{
  "name": "Gimnasio Atlas",
  "short_name": "Atlas",
  "display": "standalone",
}

[HTML] En un sprite SVG, ¿cómo se muestra el icono definido con <symbol id="i-lupa">?

[HTML] ¿Qué le falta a este botón para ser accesible?
<button type="button">
  <svg aria-hidden="true"><use href="#i-cerrar"></use></svg>
</button>

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.