Reducir el tamaño de la fuente web

La tipografía es fundamental para un buen diseño, la marca, la legibilidad y la accesibilidad. Las fuentes web permiten todo lo anterior y mucho más: el texto se puede seleccionar, buscar, ampliar y es compatible con pantallas de alta resolución, lo que proporciona una renderización de texto coherente y nítida, independientemente del tamaño y la resolución de la pantalla. Las WebFonts son fundamentales para un buen diseño, UX y rendimiento.

La optimización de las fuentes web es una parte fundamental de la estrategia general de rendimiento. Cada fuente es un recurso adicional, y algunas fuentes pueden bloquear la renderización del texto, pero el hecho de que la página use WebFonts no significa que se tenga que renderizar más lento. Por el contrario, las fuentes optimizadas, combinadas con una estrategia juiciosa sobre cómo se cargan y aplican en la página, pueden ayudar a reducir el tamaño total de la página y mejorar los tiempos de renderización.

Anatomía de una fuente web

Una fuente web es una colección de glifos, y cada glifo es una forma vectorial que describe una letra o un símbolo. Como resultado, dos variables simples determinan el tamaño de un archivo de fuente en particular: la complejidad de las rutas vectoriales de cada glifo y la cantidad de glifos en una fuente en particular. Por ejemplo, Open Sans, que es una de las WebFonts más populares, contiene 897 glifos, que incluyen caracteres latinos, griegos y cirílicos.

Tabla de glifos de fuentes

Cuando elijas una fuente, es importante que tengas en cuenta qué conjuntos de caracteres se admiten. Si necesitas localizar el contenido de tu página en varios idiomas, debes usar una fuente que pueda brindar una apariencia y una experiencia coherentes a tus usuarios. Por ejemplo, la familia de fuentes Noto de Google tiene como objetivo admitir todos los idiomas del mundo. Sin embargo, ten en cuenta que el tamaño total de Noto, con todos los idiomas incluidos, genera una descarga de ZIP de más de 1.1 GB.

En esta publicación, descubrirás cómo reducir el tamaño de archivo entregado de tus fuentes web.

Formatos de fuentes web

Actualmente, se utilizan dos formatos de contenedores de fuentes recomendados en la Web:

WOFF y WOFF 2.0 son ampliamente compatibles con todos los navegadores modernos.

  • Publica la variante WOFF 2.0 en navegadores modernos.
  • Si es absolutamente necesario (por ejemplo, si aún necesitas admitir Internet Explorer 11), publica el formato WOFF como alternativa.
  • Como alternativa, considera no usar fuentes web para los navegadores heredados y recurrir a las fuentes del sistema. Esto también puede ser más eficiente para dispositivos más antiguos y con más limitaciones.
  • Dado que WOFF y WOFF 2.0 abarcan todas las bases para los navegadores modernos y heredados que aún se usan, ya no es necesario usar EOT ni TTF, y esto puede generar tiempos de descarga más largos de las fuentes web.

Fuentes web y compresión

Tanto WOFF como WOFF 2.0 tienen compresión integrada. La compresión interna de WOFF 2.0 usa Brotli y ofrece hasta un 30% más de compresión que WOFF. Para obtener más información, consulta el informe de evaluación de WOFF 2.0.

Por último, vale la pena destacar que algunos formatos de fuentes contienen metadatos adicionales, como sugerencias de fuentes y kerning, que pueden no ser necesarios en algunas plataformas, lo que permite una mayor optimización del tamaño del archivo. Por ejemplo, Google Fonts mantiene más de 30 variantes optimizadas para cada fuente y detecta y entrega automáticamente la variante óptima para cada plataforma y navegador.

Cómo definir una familia de fuentes con @font-face

La regla @ @font-face de CSS te permite definir la ubicación de un recurso de fuente en particular, sus características de estilo y los puntos de código Unicode para los que se debe usar. Se puede usar una combinación de esas declaraciones de @font-face para construir una "familia de fuentes", que el navegador usará para evaluar qué recursos de fuentes se deben descargar y aplicar a la página actual.

Considera usar una fuente variable

Las fuentes variables pueden reducir significativamente el tamaño de archivo de tus fuentes en los casos en los que necesites varias variantes de una fuente. En lugar de tener que cargar los estilos normal y negrita, además de sus versiones en cursiva, puedes cargar un solo archivo que contenga toda la información. Sin embargo, los tamaños de los archivos de fuentes variables serán más grandes que los de una variante de fuente individual, aunque más pequeños que la combinación de muchas variantes. En lugar de una fuente variable grande, puede ser mejor publicar primero las variantes de fuentes críticas y descargar otras variantes más tarde.

Todos los navegadores modernos ahora admiten las fuentes variables. Obtén más información en la Introducción a las fuentes variables en la Web.

Selecciona el formato adecuado

Cada declaración @font-face proporciona el nombre de la familia de fuentes, que actúa como un grupo lógico de varias declaraciones, propiedades de fuentes, como el estilo, el grosor y la expansión, y el descriptor src, que especifica una lista priorizada de ubicaciones para el recurso de fuentes.

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome.woff2') format('woff2'),
       /* Only serve WOFF if necessary. Otherwise,
          WOFF 2.0 is fine by itself. */
       url('/fonts/awesome.woff') format('woff');
}

@font-face {
  font-family: 'Awesome Font';
  font-style: italic;
  font-weight: 400;
  src: local('Awesome Font Italic'),
       url('/fonts/awesome-i.woff2') format('woff2'),
       url('/fonts/awesome-i.woff') format('woff');
}

Primero, ten en cuenta que los ejemplos anteriores definen una sola familia Awesome Font con dos estilos (normal y cursiva), cada uno de los cuales apunta a un conjunto diferente de recursos de fuentes. A su vez, cada descriptor src contiene una lista priorizada y separada por comas de variantes de recursos:

  • La directiva local() te permite hacer referencia a fuentes instaladas de forma local, cargarlas y usarlas. Si el usuario ya tiene la fuente instalada en su sistema, se omite la red por completo, lo que resulta en la opción más rápida.
  • La directiva url() te permite cargar fuentes externas y puede contener una sugerencia format() opcional que indique el formato de la fuente a la que se hace referencia en la URL proporcionada.

Cuando el navegador determina que se necesita la fuente, itera a través de la lista de recursos proporcionada en el orden especificado y trata de cargar el recurso adecuado. Por ejemplo, siguiendo el ejemplo anterior:

  1. El navegador realiza el diseño de la página y determina qué variantes de fuente se requieren para renderizar el texto especificado en la página. El navegador no descarga las fuentes que no forman parte del Modelo de objetos CSS (CSSOM) de la página, ya que no son necesarias.
  2. Para cada fuente requerida, el navegador verifica si está disponible de forma local.
  3. Si la fuente no está disponible de forma local, el navegador itera sobre las definiciones externas:
    • Si hay una sugerencia de formato, el navegador verifica si la admite antes de iniciar la descarga. Si el navegador no admite la sugerencia, avanza a la siguiente.
    • Si no hay ninguna sugerencia de formato, el navegador descarga el recurso.

La combinación de directivas locales y externas con sugerencias de formato adecuadas te permite especificar todos los formatos de fuentes disponibles y dejar que el navegador se encargue del resto. El navegador determina qué recursos son necesarios y selecciona el formato óptimo.

Subconjunto de Unicode-range

Además de las propiedades de la fuente, como el estilo, el peso y la expansión, la regla @font-face te permite definir un conjunto de puntos de código Unicode admitidos por cada recurso. Esto te permite dividir una fuente Unicode grande en subconjuntos más pequeños (por ejemplo, subconjuntos latinos, cirílicos y griegos) y descargar solo los glifos necesarios para renderizar el texto en una página en particular.

El descriptor unicode-range te permite especificar una lista de valores de rango delimitados por comas, cada uno de los cuales puede tener una de las tres formas diferentes:

  • Un solo punto de código (por ejemplo, U+416)
  • Rango de intervalo (por ejemplo, U+400-4ff): Indica los puntos de código de inicio y finalización de un rango.
  • Rango de comodines (por ejemplo, U+4??): Los caracteres ? indican cualquier dígito hexadecimal.

Por ejemplo, puedes dividir tu familia de Awesome Font en subconjuntos de caracteres latinos y japoneses, cada uno de los cuales el navegador descarga según sea necesario:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-jp.woff2') format('woff2');
  /* Japanese glyphs */
  unicode-range: U+3000-9FFF, U+ff??;
}

El uso de subconjuntos de rangos Unicode y archivos separados para cada variante estilística de la fuente te permite definir una familia de fuentes compuesta que es más rápida y eficiente para descargar. Los visitantes solo descargan las variantes y los subconjuntos que necesitan, y no se ven obligados a descargar subconjuntos que tal vez nunca vean o usen en la página.

Casi todos los navegadores admiten unicode-range. Para lograr la compatibilidad con navegadores anteriores, es posible que debas recurrir a la "creación manual de subconjuntos". En este caso, debes proporcionar un solo recurso de fuente que contenga todos los subconjuntos necesarios y ocultar el resto del navegador. Por ejemplo, si la página solo usa caracteres latinos, puedes quitar otros glifos y publicar ese subconjunto en particular como un recurso independiente.

  1. Determina qué subconjuntos son necesarios:
    • Si el navegador admite la creación de subconjuntos de unicode-range, seleccionará automáticamente el subconjunto correcto. La página solo debe proporcionar los archivos de subconjunto y especificar los rangos de Unicode adecuados en las reglas @font-face.
    • Si el navegador no admite la creación de subconjuntos de unicode-range, la página debe ocultar todos los subconjuntos innecesarios, es decir, el desarrollador debe especificar los subconjuntos requeridos.
  2. Genera subconjuntos de fuentes:
    • Usa la herramienta pyftsubset de código abierto para crear subconjuntos y optimizar tus fuentes.
    • Algunos servidores de fuentes, como Google Fonts, crearán automáticamente subconjuntos de forma predeterminada.
    • Algunos servicios de fuentes permiten la creación manual de subconjuntos a través de parámetros de consulta personalizados, que puedes usar para especificar manualmente el subconjunto requerido para tu página. Consulta la documentación de tu proveedor de fuentes.

Selección y síntesis de fuentes

Cada familia de fuentes puede estar compuesta por múltiples variantes de estilo (normal, negrita, cursiva) y múltiples pesos para cada estilo. Cada uno de ellos, a su vez, puede contener formas de glifos muy diferentes, por ejemplo, diferentes espaciados, tamaños o una forma completamente diferente.

Grosor de la fuente

En el diagrama anterior, se ilustra una familia de fuentes que ofrece tres pesos de negrita diferentes:

  • 400 (común).
  • 700 (negrita).
  • 900 (extrabold)

Todas las demás variantes intermedias (indicadas en gris) se asignan automáticamente a la variante más cercana por el navegador.

Cuando se especifica un peso para el que no existe un rostro, se usa un rostro con un peso cercano. En general, los pesos en negrita se asignan a caras con pesos más gruesos, y los pesos claros se asignan a caras con pesos más finos.

Algoritmo de coincidencia de fuentes de CSS

Una lógica similar se aplica a las variantes en cursiva. El diseñador de fuentes controla qué variantes producirá, y tú controlas qué variantes usarás en la página. Como cada variante es una descarga independiente, es una buena idea mantener la cantidad de variantes baja. Por ejemplo, puedes definir dos variantes en negrita para la familia Awesome Font:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 700;
  src: local('Awesome Font'),
       url('/fonts/awesome-l-700.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

En el ejemplo anterior, se declara la familia Awesome Font, que se compone de dos recursos que abarcan el mismo conjunto de glifos latinos (U+000-5FF), pero ofrecen dos "pesos" diferentes: normal (400) y negrita (700). Sin embargo, ¿qué sucede si una de tus reglas CSS especifica un grosor de fuente diferente o establece la propiedad font-style en italic?

  • Si no hay una coincidencia exacta de la fuente, el navegador sustituye la coincidencia más cercana.
  • Si no se encuentra ninguna coincidencia de estilo (por ejemplo, no se declararon variantes en cursiva en el ejemplo anterior), el navegador sintetiza su propia variante de fuente.
Síntesis de fuentes

En el ejemplo anterior, se ilustra la diferencia entre los resultados de la fuente real y la sintetizada para Open Sans. Todas las variantes sintetizadas se generan a partir de una sola fuente de 400 pesos. Como puedes ver, hay una diferencia notable en los resultados. No se especifican los detalles para generar las variantes en negrita y oblicua. Por lo tanto, los resultados varían de un navegador a otro y dependen en gran medida de la fuente.

Lista de tareas para optimizar el tamaño de la fuente web

  • Audita y supervisa el uso de fuentes: No uses demasiadas fuentes en tus páginas y, para cada fuente, minimiza la cantidad de variantes utilizadas. Esto ayuda a brindar una experiencia más coherente y rápida para tus usuarios.
  • Evita los formatos heredados si es posible: Los formatos EOT, TTF y WOFF son más grandes que WOFF 2.0. Los formatos EOT y TTF son estrictamente innecesarios, mientras que WOFF puede ser aceptable si necesitas admitir Internet Explorer 11. Si solo segmentas tus anuncios para navegadores modernos, usar solo WOFF 2.0 es la opción más simple y con mejor rendimiento.
  • Crea subconjuntos de tus recursos de fuentes: Muchas fuentes se pueden dividir en subconjuntos o en varios rangos de Unicode para entregar solo los glifos que requiere una página en particular. Esto reduce el tamaño del archivo y mejora la velocidad de descarga del recurso. Sin embargo, cuando definas los subconjuntos, ten cuidado de optimizar la reutilización de fuentes. Por ejemplo, no descargues un conjunto diferente, pero superpuesto, de caracteres en cada página. Una buena práctica es crear subconjuntos según la escritura, por ejemplo, latina y cirílica.
  • Prioriza local() en tu lista de src: Si colocas local('Font Name') primero en tu lista de src, te aseguras de que no se realicen solicitudes HTTP para las fuentes que ya están instaladas.
  • Usa Lighthouse para probar la compresión de texto.

Efectos en el Largest Contentful Paint (LCP) y el Cumulative Layout Shift (CLS)

Según el contenido de tu página, los nodos de texto se pueden considerar candidatos para el Largest Contentful Paint (LCP). Por lo tanto, es fundamental que te asegures de que tus fuentes web sean lo más pequeñas posible siguiendo los consejos de este artículo para que tus usuarios vean el texto en tu página lo antes posible.

Si te preocupa que, a pesar de tus esfuerzos de optimización, el texto de la página tarde demasiado en aparecer debido a un recurso de fuente web grande, la propiedad font-display tiene varios parámetros de configuración que pueden ayudarte a evitar el texto invisible mientras se descarga una fuente. Sin embargo, usar el valor swap puede provocar cambios de diseño significativos que afecten el Cumulative Layout Shift (CLS) de tu sitio. Considera usar los valores optional o fallback si es posible.

Si tus fuentes web son fundamentales para tu marca y, por extensión, para la experiencia del usuario, considera precargarlas para que el navegador tenga una ventaja inicial en la solicitud. Esto puede reducir el período de intercambio si usas font-display: swap o el período de bloqueo si no usas font-display.