Plus d'options de police variables pour la police de l'UI système de macOS dans Chromium 83

Catalina apporte une nouvelle police système variable unifiée à macOS.

La section "system-ui" de la spécification CSS Fonts Module Level 4 définit un mot clé de police system-ui qui permet aux développeurs d'utiliser la police par défaut du système d'exploitation directement dans leurs sites et applications. Cette police est intégrée, turbo-optimisée, localisée, de très haute qualité et ne nécessite aucun téléchargement.

body {
  font-family: system-ui;
}

Ce choix typographique revient à dire "utiliser la police système par défaut pour les paramètres régionaux actuels de cet utilisateur".

Sur macOS, la police system-ui est San Francisco, une police qui a été examinée, testée et… récemment mise à niveau par une équipe de conception. Nous allons d'abord aborder les nouvelles fonctionnalités intéressantes des polices variables dans Catalina, puis nous verrons quelques bugs et comment les ingénieurs Chromium les ont résolus.

Cet article part du principe que vous connaissez déjà les polices variables. Si ce n'est pas le cas, consultez Introduction aux polices variables sur le Web et la vidéo ci-dessous.

Compatibilité du navigateur

Au moment de la rédaction de cet article, system-ui est compatible avec Chromium (depuis la version 56), Edge (depuis la version 79), Safari (depuis la version 11) et Firefox (depuis la version 43), mais avec le mot clé -apple-system. Pour en savoir plus, consultez Puis-je utiliser des polices variables ?

Nouveaux pouvoirs

Les nouvelles fonctionnalités que Catalina a apportées à la police système sont désormais disponibles pour les développeurs Web à partir de Chromium 83. La police system-ui propose désormais davantage de paramètres variables : taille optique et deux ajustements d'épaisseur uniques :

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
  ;
}

Sur Mojave, system-ui est une police variable avec seulement wght paramètres. Sur Catalina, system-ui est une police variable avec des paramètres wght, opsz, GRAD et YAXS.

Il me semble que nous avons là de belles opportunités de conception pour l'amélioration progressive ! Si vous le souhaitez, vous pouvez vraiment vous pencher sur les subtilités de la typographie système.

wght

Accepte une épaisseur de police comprise entre 0 et 900, et s'applique de manière égale à tous les caractères.

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

opsz

La taille optique est semblable à l'approche ou à l'espacement des lettres, mais l'espacement est effectué par un œil humain plutôt que par un calcul mathématique. Une valeur de 19 ou moins est destinée à l'espacement du texte et du corps du texte, tandis qu'une valeur de 20 ou plus est destinée à l'espacement des en-têtes et des titres.

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

GRAD

Semblable à la pondération, mais sans toucher l'espacement horizontal. Il accepte les valeurs comprises entre 400 et 1000.

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

YAXS

Étend le glyphe verticalement. Il accepte les valeurs comprises entre 400 et 1000.

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

Combiner les options

Avec quelques lignes de CSS, nous pouvons modifier les paramètres de police pour choisir une épaisseur de notre choix ou essayer d'autres combinaisons intéressantes :

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

Et voilà ! Les utilisateurs de Chromium sur macOS voient votre version personnalisée de la police avec une épaisseur de 750, ainsi que d'autres modifications amusantes 👍

macOS 10.15 a ajouté de nouvelles fonctionnalités à sa police système. Dans macOS 10.15, un bug system-ui délicat a été enregistré dans le système de suivi des bugs Chromium. Je me demande s'ils sont liés !

Annexe : Régression system-ui

Cette histoire commence par un autre bug : #1005969. Ce problème a été signalé sur macOS 10.15, car l'espacement de la police system-ui semblait étroit et compressé.

Comparaison de deux paragraphes d'une page de groupe Facebook. À gauche, Chrome et à droite, Safari. L'espacement de Chrome est subtil, mais légèrement plus serré.
Chrome à gauche (suivi plus précis), Safari à droite (espacement optique plus adapté)

Arrière-plan

Avez-vous déjà remarqué que sur macOS 10.14, vos paragraphes ou vos en-têtes "s'accrochaient" à une police différente lorsque la taille augmentait ou diminuait ?

Sur Mojave (macOS 10.14), la police system-ui alternait entre deux polices en fonction de la taille de police cible. Lorsque le texte était inférieur à 20px, macOS utilisait "San Francisco Text". Lorsque la taille du texte était égale ou supérieure à 20px, macOS utilisait "San Francisco Display". La taille optique a été intégrée de manière statique dans deux polices distinctes.

Catalina (macOS 10.15) a introduit une nouvelle police variable unifiée pour San Francisco. Vous n'avez plus besoin de gérer les campagnes "Texte" et "Display". Il a également été doté du nouveau paramètre de variante opsz décrit précédemment.

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

Malheureusement, la valeur par défaut opsz de la nouvelle police Catalina est 20, et les ingénieurs Chromium n'étaient pas prêts à appliquer opsz à la police système. Cela a entraîné un affichage trop étroit pour les petites tailles.

Pour résoudre ce problème, Chromium devait appliquer correctement opsz à la police système. Cela a permis de résoudre le problème 1005969. Gagné ! Ou était-ce…?

Pas encore terminé

C'est là que les choses se sont compliquées : Chromium a appliqué opsz, mais quelque chose ne semblait toujours pas correct. Sur Mac, les polices système comportent une table de polices supplémentaire appelée trak, qui modifie l'espacement horizontal. Lors de la résolution du problème, les ingénieurs Chromium ont remarqué que sur macOS, lors de la récupération des métriques horizontales à partir d'un objet CTFontRef, les métriques trak étaient déjà prises en compte dans les résultats des métriques. La bibliothèque de mise en forme de Chromium HarfBuzz a besoin de métriques dans lesquelles les valeurs trak ne sont pas encore prises en compte.

Affichage de system-ui et de toutes ses variantes et épaisseurs de police dans une liste. La moitié d'entre eux n'ont pas de différences de poids appliquées.
À gauche : épaisseur de police en gras appliquée aux tailles de police 19 et inférieures. À droite : la mise en gras disparaît pour les tailles de police supérieures ou égales à 20

En interne, Skia (la bibliothèque graphique, et non la typographie du même nom) utilise à la fois la classe CGFontRef de CoreGraphics et la classe CTFontRef de CoreText. En raison des conversions internes requises entre ces objets (utilisés pour assurer la rétrocompatibilité et accéder aux API nécessaires sur les deux classes), Skia perdrait des informations sur la graisse dans certaines circonstances et les polices en gras cesseraient de fonctionner. Ce problème a été suivi dans le problème 1057654.

Skia doit toujours être compatible avec macOS 10.11, car Chromium l'est toujours. Sur la version 10.11, les polices "San Francisco Text" et "San Francisco Display" n'étaient même pas des polices variables. Chacune d'elles était plutôt une famille de polices distinctes pour chaque épaisseur disponible. À un moment donné, leurs ID de glyphe ont été désynchronisés. Ainsi, si Skia met en forme du texte (en le convertissant en glyphes pouvant être dessinés) avec "San Francisco Text", le résultat sera incompréhensible s'il est dessiné avec "San Francisco Display", et inversement. Même si Skia demande une taille différente, macOS peut passer à l'autre. Il devrait être possible d'utiliser l'une des polices et de la mettre à l'échelle (en utilisant une matrice pour l'agrandir au lieu de demander une taille plus grande), mais CoreText présente un problème qui empêche la mise à l'échelle des glyphes sbix (emoji en couleur) vers le haut (uniquement vers le bas). C'est un peu plus complexe que ça. CoreText semble en fait limiter l'étendue verticale après l'application de la matrice, ce qui semble lié à l'impossibilité de dessiner des emoji à des angles de 45 degrés. Dans tous les cas, si vous souhaitez que votre emoji soit affiché en grand, vous devez faire une copie de la police pour obtenir une version plus grande.

Pour créer des copies d'objets CTFont de différentes tailles en interne tout en s'assurant que les mêmes données de police sous-jacentes sont utilisées, Chromium a extrait le CGFont du CTFont, puis a créé un CTFont à partir du CGFont (les objets CGFont sont indépendants de la taille, la commutation magique se produit au niveau CoreText). Cela fonctionnait bien jusqu'à la version 10.154. Dans la version 10.15, ce cycle a entraîné une perte d'informations trop importante, ce qui a causé le problème de poids. Flutter a détecté le problème de poids et une autre solution de correction du redimensionnement a été trouvée pour créer le nouveau CTFont directement à partir du CTFont d'origine, tout en contrôlant la taille optique directement à l'aide d'un ancien attribut non documenté dans CoreText. Cela permet de continuer à utiliser la version 10.11 et de résoudre d'autres problèmes (comme la définition explicite de la taille optique sur la valeur par défaut).

Toutefois, cela préserve davantage la "magie" de CoreText dans la police. L'un d'eux semble être qu'il modifie toujours les avances de glyphes d'une manière autre que la table trak (dont Chromium essayait déjà de supprimer l'application par le biais d'un autre attribut non documenté).

CGFont n'effectue aucune de ces "magies". Peut-être que Chromium pourrait supprimer le CGFont du CTFont et l'utiliser simplement pour obtenir des avancées ? Malheureusement, cela ne fonctionnerait pas, car CoreText est également connu pour modifier les polices d'autres manières. Par exemple, il agrandit légèrement les petits emoji par rapport à la taille que vous avez demandée. CGFont ne le sait pas, vous vous retrouveriez donc avec vos emoji basés sur sbix trop proches les uns des autres, car vous les mesureriez à une taille, mais CoreText les dessinerait plus grands d'une certaine quantité. Chromium souhaite bénéficier des avancées de CTFont, mais sans suivi et, de préférence, sans autre manipulation.

Étant donné que la correction du problème d'espacement nécessitait un ensemble de correctifs Blink et Skia interconnectés, les ingénieurs Chromium ne pouvaient pas simplement revenir en arrière pour résoudre le problème. Les ingénieurs Chromium ont également essayé d'utiliser un autre indicateur de compilation pour modifier un chemin de code lié à la police dans Skia, ce qui a résolu le problème des polices en gras, mais a aggravé le problème d'espacement.

Solution

Finalement, Chromium a souhaité corriger les deux problèmes. Chromium utilise désormais les fonctions de métriques de police OpenType intégrées à HarfBuzz pour récupérer les métriques horizontales directement à partir des données binaires des tables de police de la police système. Chromium contourne ainsi CoreText et Skia lorsque la police comporte une table trak (sauf s'il s'agit de la police d'emoji).

Affichage de system-ui et de toutes ses variantes et épaisseurs de police dans une liste. La moitié qui ne fonctionnait pas auparavant est désormais parfaite.

En attendant, vous pouvez toujours suivre le problème 10123 de Skia pour savoir quand ce problème sera entièrement résolu dans Skia. Vous pourrez alors à nouveau utiliser Skia pour récupérer les métriques de la police système, au lieu de la solution actuelle qui passe par HarfBuzz.