Fontes substitutas aprimoradas

Katie hempenius
Katie Hempenius

Resumo

Este artigo apresenta uma análise detalhada dos substitutos de fonte e das APIs size-adjust, ascent-override, descent-override e line-gap-override. Essas APIs possibilitam o uso de fontes locais para criar fontes substitutas que correspondem exatamente às dimensões de uma fonte da Web. Isso reduz ou elimina as mudanças de layout causadas pela troca de fontes.

Se você preferir pular a leitura deste artigo, estas são algumas das ferramentas que podem ser usadas para começar a usar essas APIs imediatamente:

Ferramentas do framework:

  • @next/font: a partir do Next 13, next/font usa automaticamente substituições de métricas de fonte e size-adjust para oferecer substitutos de fonte correspondentes.
  • @nuxtjs/fontaine: a partir do Nuxt 3, você pode usar nuxt/fontaine para gerar e inserir substitutos de fonte correspondentes automaticamente nas folhas de estilo usadas pelo app Nuxt.

Ferramentas que não são do framework:

  • Fontaine: é uma biblioteca que gera e insere automaticamente fontes substitutas que usam substituições de métricas de fonte.
  • Este repositório (link em inglês) contém as substituições de métrica de fontes para todas as fontes hospedadas pelo Google Fonts. Esses valores podem ser copiados e colados em suas folhas de estilo.

Contexto

A fonte substituta é usada quando a principal ainda não foi carregada ou não tem os glifos necessários para renderizar o conteúdo da página. Por exemplo, o CSS abaixo indica que a família de fontes sans-serif precisa ser usada como substituto de fonte para "Roboto".

font-family: "Roboto" , sans-serif;

Fontes substitutas podem ser usadas para renderizar texto mais rapidamente, ou seja, usando font-display: swap. Como resultado, o conteúdo da página passa a ser legível e útil mais cedo. No entanto, historicamente, isso causou a instabilidade do layout: mudanças de layout geralmente ocorrem quando uma fonte substituta é trocada pela fonte da Web. No entanto, as novas APIs discutidas abaixo podem reduzir ou eliminar esse problema, possibilitando a criação de tipos de fontes substitutas que ocupam a mesma quantidade de espaço que as fontes da Web.

Fontes substitutas aprimoradas

Há duas abordagens possíveis para gerar substitutos de fonte "aprimorados". A abordagem mais simples usa apenas a métrica de fonte que substitui a API. A abordagem mais complicada (mas mais eficiente) usa a métrica de fonte que substitui a API e o size-adjust. Este artigo explica as duas abordagens.

Como funcionam as substituições de métrica de fonte

Introdução

As substituições de métrica de fonte oferecem uma maneira de substituir os níveis em ordem crescente, descendente e intervalo de linha de uma fonte:

  • Ascent mede a maior distância que os glifos de uma fonte se estendem acima da linha de base.
  • Descida mede a maior distância que os glifos de uma fonte se estendem abaixo da linha de base.
  • O intervalo de linha, também chamado de "livre", mede a distância entre linhas sucessivas de texto.

Diagrama representando a subida, a descida e a lacuna de linha de uma fonte.

As substituições de métrica de fonte podem ser usadas para substituir os níveis em ordem crescente, descendente e a lacuna de linha de uma fonte substituta para que eles correspondam aos graus de subida, descida e intervalo da fonte da Web. Como resultado, a fonte da Web e a fonte substituta ajustada sempre terão as mesmas dimensões verticais.

As substituições de métrica de fonte são usadas em uma folha de estilo como esta:

body {
    font-family: Poppins, "fallback for poppins";
}

@font-face {
    font-family: "fallback for poppins";
    src: local("Times New Roman");
    ascent-override: 105%;
    descent-override: 35%;
    line-gap-override: 10%;
}

As ferramentas listadas no início deste artigo podem gerar os valores corretos de substituição da métrica de fonte. No entanto, você também pode calcular esses valores por conta própria.

Calcular substituições de métricas de fonte

As equações a seguir geram as substituições da métrica de fonte para uma determinada fonte da Web. Os valores das substituições de métricas de fonte precisam ser escritos como porcentagens (por exemplo, 105%) em vez de decimais.

ascent-override = ascent/unitsPerEm
descent-override = descent/unitsPerEm
line-gap-override = line-gap/unitsPerEm

Por exemplo, estas são as substituições de métrica de fonte para a fonte Poppins:

/*
Poppins font metrics:
ascent = 1050
descent = 350
line-gap = 100
UPM: 1000
*/

ascent-override: 105%;  /* = 1050/1000 */
descent-override: 35%;  /* = 350/1000 */
line-gap-override: 10%; /* = 100/1000 */

Os valores de ascent, descent, line-gap e unitsPerEm são provenientes dos metadados da fonte da Web. A próxima seção deste artigo explica como conseguir esses valores.

Ler tabelas de fontes

Os metadados de uma fonte (especificamente, as tabelas de fonte) contêm todas as informações necessárias para calcular as substituições de métrica da fonte.

Captura de tela da caixa de diálogo "Font Information" no FontForge. A caixa de diálogo exibe métricas de fonte, como "Typo Ascent", "Typo Descent" e "Typo Line Gap".
Usar o FontForge para ver metadados de fontes

Aqui estão algumas ferramentas que podem ser usadas para ler os metadados de uma fonte:

  • O fontkit é um mecanismo de fontes criado para o Node.js. Este snippet de código mostra como usar o fontkit para calcular as substituições de métrica da fonte.
  • O Capsize (link em inglês) é uma biblioteca de layout e tamanho de fontes. O Capsize fornece uma API para receber informações sobre várias métricas de fonte.
  • fontdrop.info é um site que permite ver tabelas de fontes e outras informações relacionadas a fontes no navegador.
  • O Font Forge é um editor de fontes conhecido para computador. Para conferir ascent, descent e line-gap: abra a caixa de diálogo Font Info, selecione o menu OS/2 e a guia Metrics. Para conferir o UPM: abra a caixa de diálogo Font Info e selecione o menu General.

Noções básicas sobre tabelas de fontes

Conceitos como "ascente" são referidos por várias métricas. Por exemplo, há métricas hheaAscent, typoAscent e winAscent. Isso é resultado de diferentes sistemas operacionais que adotam abordagens diferentes para a renderização de fontes: os programas em dispositivos OSX geralmente usam métricas de fonte hhea*, enquanto os programas em dispositivos Windows geralmente usam métricas de fonte typo* (também chamadas de sTypo*) ou win*.

Dependendo da fonte, do navegador e do sistema operacional, uma fonte é renderizada usando as métricas hhea, typo ou win.

Mac Windows
Chromium Usa métricas da tabela "hhea". Usa métricas da tabela "typo" se "USE_TYPO_METRICS" tiver sido definida. Caso contrário, usa as métricas da tabela "win".
Firefox Usa métricas da tabela "typo" se "USE_TYPO_METRICS" tiver sido definida. Caso contrário, usa as métricas da tabela "hhea". Usa métricas da tabela "typo" se "USE_TYPO_METRICS" tiver sido definida. Caso contrário, usa as métricas da tabela "win".
Safari Usa métricas da tabela "hhea". Usa métricas da tabela "typo" se "USE_TYPO_METRICS" tiver sido definida. Caso contrário, usa as métricas da tabela "win".

Para mais informações sobre como as métricas de fontes funcionam em todos os sistemas operacionais, consulte este artigo sobre métricas verticais.

Compatibilidade entre dispositivos

Para a grande maioria das fontes (por exemplo, cerca de 90% das fontes hospedadas pelo Google Fonts), as substituições de métricas podem ser usadas com segurança sem conhecer o sistema operacional do usuário. Em outras palavras, para essas fontes, os valores de ascent-override, descent-override e linegap-override permanecem exatamente os mesmos, independente da aplicação das métricas hhea, typo ou win. Este repositório (link em inglês) fornece informações sobre quais fontes isso se aplica ou não.

Se você estiver usando uma fonte que exija o uso de conjuntos separados de substituições de métricas de fonte para dispositivos OSX e Windows, o uso de substituições de métricas de fonte e size-adjust só é recomendado se você puder variar suas folhas de estilo com base no sistema operacional do usuário.

Como usar substituições de métricas de fonte

Como as substituições de métrica de fonte são calculadas usando medidas provenientes dos metadados da fonte da Web (e não da fonte substituta), elas permanecem as mesmas, independentemente de qual fonte é usada como substituta. Exemplo:

body {
  font-family: "Poppins", "fallback for Poppins", "another fallback for Poppins";
}

@font-face {
  font-family: "fallback for Poppins";
  src: local("Arial");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

@font-face {
  font-family: "another fallback for Poppins";
  src: local("Roboto");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

Como o ajuste de tamanho funciona

Introdução

O descritor CSS size-adjust dimensiona proporcionalmente a largura e a altura dos glifos da fonte. Por exemplo, size-adjust: 200% dimensiona os glifos de fonte para o dobro do tamanho original; size-adjust: 50% dimensiona os glifos de fonte para metade do tamanho original.

Diagrama mostrando os resultados do uso de "size-adjust: 50%" e "size-adjust: 200%".

Por si só, o size-adjust tem aplicativos limitados para melhorar os substitutos de fonte: na maioria dos casos, uma fonte substituta precisa ser estreita ou ampliada um pouco (em vez de dimensionada proporcionalmente) para corresponder a uma fonte da Web. No entanto, a combinação de size-adjust com substituições de métricas de fonte possibilita fazer com que duas fontes correspondam horizontal e verticalmente.

Veja como size-adjust é usado em folhas de estilo:

@font-face {
  font-family: "fallback for poppins";
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

Devido à forma como size-adjust é calculado (o que é explicado na próxima seção), o valor de size-adjust (e as substituições da métrica de fonte correspondente) muda dependendo de qual fonte substituta é usada:

body {
  font-family: "Poppins", "fallback for Poppins", "another fallback for Poppins";
}

@font-face {
  font-family: poppins-fallback;
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

@font-face {
  font-family: poppins-fallback-android;
  src: local("Roboto");
  size-adjust: 55.5193474%:
  ascent-override: 180.1173909%;
  descent-override: 63.04108683%;
  line-gap-override: 18.01173909%;
}

Como calcular substituições de métricas de fonte e ajuste de tamanho

Estas são as equações para calcular size-adjust e substituições de métricas de fonte:

size-adjust = avgCharacterWidth of web font / avgCharacterWidth of fallback font
ascent-override = web font ascent / (web font UPM * size-adjust)
descent-override = web font descent / (web font UPM * size-adjust)
line-gap-override = web font line-gap / (web font UPM * size-adjust)

A maioria dessas entradas (ou seja, subida, descida e intervalo de linha) pode ser lida diretamente dos metadados da fonte da Web. No entanto, avgCharacterWidth precisa ser aproximado.

Largura média aproximada de caracteres

Em geral, a largura média de caracteres só pode ser aproximada, mas há alguns cenários em que isso pode ser calculado exatamente. Por exemplo, ao usar uma fonte monoespaçada ou quando o conteúdo de uma string de texto é conhecido com antecedência.

Um exemplo de abordagem simples para calcular avgCharacterWidth é usar a largura média de todos os caracteres [a-z\s].

 Gráfico comparando a largura de glifos de Roboto [a-zs] individuais.
Largura dos glifos Roboto

No entanto, ponderar todos os caracteres da mesma forma provavelmente diminuirá o peso das letras usadas com frequência (por exemplo, e) e da largura das letras usadas com pouca frequência (por exemplo, z).

Uma abordagem mais complexa que melhora a precisão é considerar a frequência de letras e calcular a largura média ponderada com frequência de [a-z\s] caracteres. Este artigo é uma boa referência sobre a frequência das letras e o comprimento médio das palavras em textos em inglês.

Um gráfico mostrando a frequência de letras em inglês.
Frequência de letras em inglês

Como escolher uma abordagem

Cada uma das duas abordagens discutidas neste artigo tem vantagens e desvantagens:

  • Usar apenas substituições de métricas de fonte é uma boa abordagem se você está começando a otimizar seus substitutos de fonte. Embora essa seja a mais simples das duas abordagens, ela normalmente é poderosa o suficiente para reduzir visivelmente a magnitude das mudanças de layout relacionadas à fonte.

  • Por outro lado, se você quiser maior precisão e quiser se esforçar um pouco mais, incorporar size-adjust é uma boa abordagem. Quando implementada corretamente, essa abordagem pode eliminar as mudanças de layout relacionadas a fontes de forma eficaz.

Escolher fontes substitutas

As técnicas descritas neste artigo dependem do uso de substituições de métricas de fonte e size-adjust para transformar fontes locais amplamente disponíveis, em vez de tentar encontrar uma fonte local que se aproxime da fonte da Web. Ao escolher fontes locais, é importante lembrar que poucas fontes têm disponibilidade local generalizada e nenhuma fonte vai existir em todos os dispositivos.

Arial é a fonte substituta recomendada para fontes sem serifa e Times New Roman é a fonte substituta recomendada para fontes com serifa. No entanto, nenhuma dessas fontes está disponível no Android (Roboto é a única fonte do sistema no Android).

O exemplo abaixo usa três fontes substitutas para garantir uma cobertura de dispositivo ampla: uma para dispositivos Windows/Mac, outra destinada a dispositivos Android e uma alternativa que usa uma família genérica de fontes.

body {
  font-family: "Poppins", poppins-fallback, poppins-fallback-android, sans-serif;
}

/*
Poppins font metrics:
- ascent = 1050
- descent = 350
- line-gap = 100
- UPM: 1000
AvgCharWidth:
- Poppins: 538.0103768
- Arial: 884.1438804
- Roboto: 969.0502537
*/

@font-face {
  font-family: poppins-fallback;
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

@font-face {
  font-family: poppins-fallback-android;
  src: local("Roboto");
  size-adjust: 55.5193474%:
  ascent-override: 180.1173909%;
  descent-override: 63.04108683%;
  line-gap-override: 18.01173909%;
}

Solicitação de feedback

Entre em contato se tiver feedback sobre sua experiência com as substituições de métricas de fonte e size-adjust.