Más opciones de fuentes variables para la fuente system-ui de macOS en Chromium 83

Catalina incorpora una nueva fuente del sistema variable unificada a macOS.

La sección "system-ui" de la especificación del módulo de fuentes CSS de nivel 4 define una palabra clave de fuente system-ui que permite a los desarrolladores usar la fuente integrada, optimizada para turbo, localizada, de calidad megaalta, sin necesidad de descarga y predeterminada del sistema operativo directamente en sus sitios y aplicaciones.

body {
  font-family: system-ui;
}

Esta elección de tipografía equivale a decir "usa la fuente predeterminada del sistema para la configuración regional actual de este usuario".

En macOS, la fuente system-ui es San Francisco, una fuente que un equipo de diseño verificó, probó y… actualizó recientemente. Primero, analizaremos las nuevas y emocionantes funciones de fuentes variables en Catalina y, luego, abordaremos algunos errores y cómo los ingenieros de Chromium los resolvieron.

En esta publicación, se supone que ya conoces las fuentes variables. De lo contrario, consulta Introducción a las fuentes variables en la Web y el siguiente video.

Compatibilidad del navegador

En el momento de escribir este artículo, system-ui es compatible con Chromium (desde la versión 56), Edge (desde la versión 79), Safari (desde la versión 11) y Firefox (desde la versión 43), pero con la palabra clave -apple-system. Consulta ¿Puedo usar fuentes variables? para obtener actualizaciones.

Nuevos poderes

Las nuevas capacidades que Catalina aportó a la fuente del sistema ahora están disponibles para los desarrolladores web a partir de Chromium 83. La fuente system-ui ahora tiene más parámetros de configuración variables: tamaño óptico y 2 ajustes de peso únicos:

Mojave
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750
  ;
}
Catalina
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750,
    'opsz' 20,
    'GRAD' 400,
    'YAXS' 400
  ;
}

En Mojave, system-ui es una fuente variable con solo parámetros de configuración de wght. Si bien system-ui en Catalina es una fuente variable con la configuración wght, opsz, GRAD y YAXS.

¡Parece que hay algunas oportunidades de diseño de mejora progresiva interesantes! Si quieres, puedes profundizar en los detalles de la fuente del sistema.

wght

Acepta un grosor de fuente entre 0 y 900, y se aplica de igual forma a todos los caracteres.

/* 0-900 */
font-variation-settings: 'wght' 750;

opsz

El tamaño óptico es similar al kerning o al espaciado entre letras, pero el espaciado se realiza a ojo en lugar de con cálculos matemáticos. Un valor de 19 o inferior se destina al espaciado del texto y del cuerpo del texto, mientras que 20 o superior se usa para el espaciado de los encabezados y títulos de la pantalla.

/* 19 or 20 */
font-variation-settings: 'opsz' 20;

GRAD

Es similar al peso, pero sin afectar el espaciado horizontal. Acepta valores entre 400 y 1000.

/* 400-1000 */
font-variation-settings: 'GRAD' 500;

YAXS

Estira el glifo verticalmente. Acepta valores entre 400 y 1000.

/* 400-1000 */
font-variation-settings: 'YAXS' 500;

Cómo combinar las opciones

Con unas pocas líneas de CSS, podemos ajustar la configuración de la fuente a una negrita de nuestra elección o probar otras combinaciones interesantes:

font-weight: 700;
font-weight: bold;
font-variation-settings: 'wght' 750, 'YAXS' 600, 'GRAD' 500, 'opsz' 20;

Y así de fácil, los usuarios de Chromium en macOS ven tu peso personalizado actualizado de 750 con otros ajustes divertidos 👍

macOS 10.15 agregó nuevas funciones a su fuente del sistema, y en macOS 10.15 se registró un error system-ui complejo en el registro de errores de Chromium. Me pregunto si están relacionados.

Apéndice: La regresión system-ui

Esta historia comienza con un error diferente: #1005969. Se informó que esto ocurría en macOS 10.15 porque el espaciado de la fuente system-ui se veía estrecho y apretado.

Comparación de dos párrafos de una página de grupo de Facebook. A la izquierda, se muestra Chrome, y a la derecha, Safari. Chrome es sutil, pero tiene un espaciado ligeramente más ajustado.
Chrome a la izquierda (seguimiento más ajustado), Safari a la derecha (mejor espaciado óptico)

Fondo

¿Alguna vez notaste en macOS 10.14 cómo tus párrafos o encabezados "encajaban" en una fuente de aspecto diferente cuando el tamaño aumentaba o disminuía?

En Mojave (macOS 10.14), la fuente system-ui cambiaba entre dos fuentes según el tamaño de fuente objetivo. Cuando el texto era inferior a 20px, macOS usaba "San Francisco Text". Cuando el texto era 20px o más, macOS usaba "San Francisco Display". El tamaño óptico se compiló de forma estática en dos fuentes separadas.

Catalina (macOS 10.15) lanzó una nueva fuente variable unificada para San Francisco. Ya no es necesario administrar las campañas de "Texto" y "Display". También se agregó el nuevo parámetro de configuración de variación opsz que se describió anteriormente.

h1 {
  font-variation-settings: 'opsz' 20;
}

Lamentablemente, el valor predeterminado de opsz en la nueva fuente Catalina es 20, y los ingenieros de Chromium no estaban preparados para aplicar opsz a la fuente del sistema. Esto provocó que los tamaños más pequeños se mostraran demasiado estrechos.

Para solucionar ese problema, Chromium debía aplicar opsz correctamente a la fuente del sistema. Esto llevó a la corrección del problema #1005969. ¡Victoria! ¿O no?

Aún no terminaste

Aquí es donde se complicó la situación: Chromium aplicó opsz, pero algo seguía sin verse bien. Las fuentes del sistema en Mac tienen una tabla de fuentes adicional llamada trak, que ajusta el espaciado horizontal. Mientras trabajaban en la corrección, los ingenieros de Chromium notaron que, en macOS, cuando se recuperaban las métricas horizontales de un objeto CTFontRef, las métricas de trak ya se incluían en los resultados de las métricas. La biblioteca de modelado de Chromium HarfBuzz necesita métricas en las que aún no se hayan tenido en cuenta los valores de trak.

Una pantalla de system-ui y todas sus variaciones y pesos de fuente en una lista. La mitad de ellos no tienen diferencias de peso aplicadas.
Izquierda: Se aplicaron pesos en negrita a tamaños de fuente de 19 y menores. Derecha: Los tamaños de fuente de 20 y superiores pierden el estilo en negrita

Internamente, Skia (la biblioteca de gráficos, no el tipo de letra del mismo nombre) usa la clase CGFontRef de CoreGraphics y la clase CTFontRef de CoreText. Debido a las conversiones internas requeridas entre esos objetos (que se usan para mantener la retrocompatibilidad y acceder a las APIs necesarias en ambas clases), Skia perdería información de peso en ciertas circunstancias y las fuentes en negrita dejarían de funcionar. Se hizo un seguimiento de este problema en Issue #1057654.

Skia aún debe admitir macOS 10.11 porque Chromium aún lo admite. El 10/11, las fuentes "San Francisco Text" y "San Francisco Display" ni siquiera eran fuentes variables. En cambio, cada una era una familia de fuentes separadas para cada peso disponible. En algún momento, sus IDs de glifos dejaron de estar sincronizados entre sí. Por lo tanto, si Skia le da forma al texto (convierte el texto en glifos que se pueden dibujar) con "San Francisco Text", se vería ilegible si se dibujara con "San Francisco Display", y viceversa. Incluso si Skia solo solicitó un tamaño diferente, macOS podría cambiar al otro. Siempre debería ser posible usar una de las fuentes y solo escalarla (usando una matriz para aumentarla en lugar de solicitar un tamaño más grande), pero CoreText tiene un problema por el que no aumentará los glifos sbix (emoji de color) (solo los reducirá). Es un poco más complejo que eso. En realidad, CoreText parece limitar la extensión vertical después de la aplicación de la matriz, lo que parece estar relacionado con el hecho de que no puede dibujar emojis en ángulos de 45 grados. En cualquier caso, si quieres que tus emojis se muestren grandes, debes hacer una copia de la fuente para obtener una versión grande.

Por lo tanto, para crear copias de objetos CTFont en diferentes tamaños de forma interna y, al mismo tiempo, garantizar que se usen los mismos datos de fuentes subyacentes, Chromium extrajo el CGFont del CTFont y, luego, creó un nuevo CTFont a partir del CGFont (los objetos CGFont son independientes del tamaño; el cambio mágico ocurre a nivel del CoreText). Esto funcionó bien hasta la versión 10.154. En 10.15, este viaje de ida y vuelta terminó perdiendo demasiada información, lo que provocó el problema de peso. Flutter notó el problema de peso y se realizó una corrección alternativa para cambiar el tamaño y crear el nuevo CTFont directamente desde el CTFont original, mientras se controlaba el tamaño óptico directamente con un atributo antiguo, pero no documentado, en CoreText. Esto permite que todo siga funcionando en 10.11 y corrige otros problemas (como establecer explícitamente el tamaño óptico en el valor predeterminado).

Sin embargo, esto conserva más la "magia" de CoreText en la fuente. Una de ellas parece ser que aún ajusta los avances de los glifos de alguna manera que no es solo la tabla trak (cuya aplicación Chromium ya intentaba suprimir a través de otro atributo no documentado).

CGFont no hace nada de esta "magia", por lo que tal vez Chromium podría quitar el CGFont del CTFont y solo usarlo para obtener avances. Lamentablemente, esto no funcionaría porque se sabe que CoreText también afecta las fuentes de otras maneras. Por ejemplo, hace que los emojis pequeños sean un poco más grandes de lo que solicitaste (aumenta un poco su tamaño). CGFont no sabe esto, por lo que los emojis basados en sbix quedarían demasiado cerca entre sí, ya que los medirías en un tamaño, pero CoreText los dibujaría más grandes en cierta cantidad. Chromium quiere los avances de CTFont, pero sin seguimiento y, preferentemente, sin ningún otro tipo de manipulación.

Dado que la solución para el problema de espaciado requería un conjunto de correcciones interconectadas de Blink y Skia, los ingenieros de Chromium no pudieron "simplemente revertir" para solucionar el problema. Los ingenieros de Chromium también intentaron usar una marca de compilación diferente para cambiar una ruta de código relacionada con las fuentes en Skia, lo que solucionó el problema de las fuentes en negrita, pero provocó una regresión en el problema de espaciado.

La solución

Al final, por supuesto, Chromium quería corregir ambas cosas. Chromium ahora recurre a las funciones integradas de métricas de fuentes OpenType de HarfBuzz para recuperar las métricas horizontales directamente de los datos binarios en las tablas de fuentes de la fuente del sistema. Con esto, Chromium evita CoreText y Skia cuando la fuente tiene una tabla trak (excepto cuando es la fuente de emojis).

Una pantalla de system-ui y todas sus variaciones y pesos de fuente en una lista. La mitad que antes no funcionaba ahora se ve excelente.

Mientras tanto, sigue existiendo el problema núm. 10123 de Skia para hacer un seguimiento de la corrección completa en Skia y volver a usar Skia para recuperar las métricas de fuentes del sistema desde allí, en lugar de la corrección actual que pasa por HarfBuzz.