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

Catalina incluye una nueva fuente del sistema variable unificada en macOS.

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

body {
  font-family: system-ui;
}

Esta elección de tipografía es similar 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 revisó, probó y… actualizó recientemente. Primero, hablaremos de las nuevas y emocionantes funciones de fuentes variables en Catalina y, luego, analizaremos algunos errores y cómo los ingenieros de Chromium los resolvieron.

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

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 funciones que Catalina incorporó 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 grosor ú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 una configuración wght. Mientras que system-ui en Catalina es una fuente variable con la configuración de wght, opsz, GRAD y YAXS.

Parecen ser buenas oportunidades de diseño de mejora progresiva. Si quieres, puedes analizar en detalle las sutilezas 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 espaciado entre letras, pero el ojo humano realiza el espaciado en lugar de la matemática. Un valor de 19 o inferior se usa para el espaciado del texto y del cuerpo, 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

Similar al peso, pero sin tocar 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;

Combina las opciones

Con unas pocas líneas de CSS, podemos modificar la configuración de la fuente para que sea negrita o probar otras combinaciones interesantes:

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

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

Área de juegos

Haz clic en Remix to Edit en el Glitch que aparece a continuación para obtener una copia editable del Glitch y, luego, edita las nuevas opciones de font-variation-settings para ver cómo afectan a tu fuente. Recuerda que este error solo funcionará si usas un dispositivo macOS Catalina.

macOS 10.15 agregó nuevas funciones a su fuente del sistema y, en macOS 10.15, se registró un error system-ui complicado en el seguimiento 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. Esto se informó en comparación con macOS 10.15 porque el espaciado de la fuente system-ui parecía estrecho y abarrotado.

Una 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)

Segundo plano

¿Alguna vez notaste en macOS 10.14 cómo tus párrafos o encabezados “cambiaban” a 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 de destino. Cuando el texto era inferior a 20px, macOS usaba "Texto San Francisco". Cuando el texto era de 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) envió una nueva fuente variable unida para San Francisco. Ya no es necesario administrar "Texto" y "Pantalla". 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 solucionarlo, Chromium debía aplicar opsz correctamente a la fuente del sistema. Esto permitió corregir el problema #1005969. ¡Victoria! ¿O no…?

Aún no se completó

Aquí es donde se complica: Chromium aplicó opsz, pero algo aún no se veía 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 métricas horizontales de un objeto CTFontRef, las métricas de trak ya se tenían en cuenta en los resultados de las métricas. La biblioteca de conformación HarfBuzz de Chromium necesita métricas en las que aún no se tengan en cuenta los valores de trak.

Una visualización de system-ui y todas sus variaciones de grosor de fuente en una lista. La mitad de ellos no tienen diferencias de peso aplicadas.
Izquierda: Se aplicaron grosores en negrita a los tamaños de fuente 19 y versiones anteriores. Derecha: Los tamaños de fuente 20 y superiores pierden el estilo en negrita.

De forma interna, 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 realizó un seguimiento de este problema en el error #1057654.

Skia aún debe ser compatible con macOS 10.11 porque Chromium lo es. El día 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 independientes para cada grosor disponible. En algún momento, sus IDs de glifos dejaron de estar sincronizados entre sí. Por lo tanto, si Skia hiciera la forma del texto (convertir el texto en glifos que se pueden dibujar) con "San Francisco Text", serí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. Debería ser posible usar siempre una de las fuentes y escalarla (con una matriz para aumentarla en lugar de pedir un tamaño más grande), pero CoreText tiene un problema que no escala los glifos sbix (emojis de colores) hacia arriba (solo hacia abajo). Es un poco más complejo que eso. CoreText parece limitar la extensión vertical después de la aplicación de la matriz, lo que parece estar relacionado con que no puede dibujar emojis en ángulos de 45 grados. En cualquier caso, si deseas que tu emoji se muestre en grande, debes hacer una copia de la fuente para obtener una versión grande.

Por lo tanto, para crear copias de objetos CTFont de diferentes tamaños de forma interna y, al mismo tiempo, garantizar que se usen los mismos datos de fuente subyacentes, Chromium extrajo el CGFont de CTFont y, luego, creó un CTFont nuevo a partir del CGFont (los objetos CGFont no dependen del tamaño, y el cambio mágico se produce a nivel de 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 solució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 sin documentar, en CoreText. De esta manera, se mantiene el funcionamiento en la versión 10.11 y se solucionan otros problemas (como configurar explícitamente el tamaño óptico en el valor predeterminado).

Sin embargo, esto conserva más de la "magia" de CoreText en la fuente. Uno de ellos parece ser que aún ajusta los avances de los glifos de alguna manera que no sea 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 quizás Chromium pueda obtener el CGFont de CTFont y simplemente usarlo para obtener avances. Lamentablemente, esto no funcionaría porque se sabe que CoreText también altera las fuentes de otras formas. Por ejemplo, hace que los emojis pequeños sean un poco más grandes de lo que en realidad solicitaste (lo cual aumenta un poco su tamaño). CGFont no lo sabe, por lo que terminarías con los emojis basados en sbix demasiado cerca unos de otros, ya que medirías un tamaño, pero CoreText los dibujaría más grandes en cierta medida. Chromium quiere los avances de CTFont, pero sin seguimiento y, de preferencia, sin ningún otro problema.

Dado que la solución del problema de espaciado requería un conjunto de correcciones interconectadas de Blink y Skia, los ingenieros de Chromium no pudieron “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 la fuente en Skia, que solucionó el problema de las fuentes en negrita, pero regresó el problema de espaciado.

La solución

Al final, por supuesto Chromium quiso corregir ambas cosas. Chromium ahora recurre al uso de las funciones de métricas de fuentes OpenType integradas en HarfBuzz para recuperar 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 visualización de system-ui y todas sus variaciones de grosor de fuente en una lista. La mitad que antes no funcionaba ahora se ve muy bien.

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