Fontes substitutas aprimoradas

Katie Hempenius
Katie Hempenius

Resumo

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

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

Ferramentas de framework:

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

Ferramentas que não são estrutura:

  • Fontaine: é uma biblioteca que gera e insere automaticamente substitutos de fonte que usam substituições de métrica de fonte.
  • Este repo contém as substituições de métrica de fonte para todas as fontes hospedadas pelo Google Fonts. Esses valores podem ser copiados e colados em suas folhas de estilo.

Contexto

Uma fonte substituta é usada quando a fonte 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 substituta 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 é legível e útil anteriormente. No entanto, historicamente, isso tem o custo da instabilidade do layout: mudanças de layout geralmente ocorrem quando uma fonte substituta é trocada por uma fonte da Web. No entanto, as novas APIs discutidas abaixo podem reduzir ou eliminar esse problema, possibilitando a criação de tipos de fonte de fallback que ocupam a mesma quantidade de espaço que a fonte da Web correspondente.

Substitutos de fonte aprimorados

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 a size-adjust. Este artigo explica as duas abordagens.

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

Introdução

As substituições de métrica de fonte oferecem uma maneira de substituir a subida, a descida e o intervalo de linha de uma fonte:

  • A subida mede a distância máxima que os glifos de uma fonte se estendem acima da linha de base.
  • A descendência mede a maior distância que os glifos de uma fonte se estendem abaixo da linha de base.
  • O intervalo entre linhas, também chamado de "início", 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 ascendente, descendente e lacuna de linha de uma fonte substituta a fim de corresponder aos níveis ascendente, descendente e de linhas 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 sozinho.

Como calcular substituições de métrica de fonte

As equações a seguir geram substituições de métricas 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.

Leitura de tabelas de fontes

Os metadados de uma fonte (especificamente, as tabelas de fontes) contêm todas as informações necessárias para calcular as substituições de métrica de 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 Lap".
Como usar o FontForge para ver metadados de fonte

Aqui estão algumas ferramentas que você pode usar para ler os metadados de uma fonte:

  • O fontkit é um mecanismo de fontes criado para Node.js. Este snippet de código mostra como usar o Fontkit para calcular substituições de métrica de fonte.
  • Capsize é um dimensionamento de fonte e uma biblioteca de layout. O Capsize fornece uma API para receber informações sobre várias métricas de fonte.
  • fontdrop.info é um site que permite visualizar tabelas de fontes e outras informações relacionadas a fontes no navegador.
  • O Font Forge é um editor de fontes muito usado para computadores. Para visualizar ascent, descent e line-gap: abra a caixa de diálogo Font Info, selecione o menu OS/2 e depois 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 "crescente" são referenciados por várias métricas. Por exemplo, há métricas hheaAscent, typoAscent e winAscent. Esse é o resultado de diferentes sistemas operacionais adotando abordagens distintas 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 será renderizada usando as métricas hhea, typo ou win.

Mac Windows
Chromium Usa métricas da tabela "hhea". Usa as métricas da tabela "typo" se "USE_TYPO_METRICS" tiver sido definida. Caso contrário, usa as métricas da tabela "win".
Firefox Usa as métricas da tabela "typo" se "USE_TYPO_METRICS" tiver sido definida. Caso contrário, usa as métricas da tabela "hhea". Usa as 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 as 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 nos sistemas operacionais, consulte este artigo sobre métricas verticais.

Compatibilidade com vários 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, independentemente das métricas hhea, typo ou win. Este repo fornece informações sobre a quais fontes isso se aplica ou não.

Se você usa uma fonte que exige 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étrica de fonte

Como as substituições de métricas de fonte são calculadas usando medidas dos metadados da fonte da Web (e não da fonte substituta), elas permanecem as mesmas, independentemente da 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 de fonte. Por exemplo, size-adjust: 200% dimensiona os glifos da fonte para o dobro do tamanho original, enquanto size-adjust: 50% dimensiona os glifos da fonte para a 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 reduzida ou ampliada um pouco (em vez de dimensionada proporcionalmente) para corresponder a uma fonte da Web. No entanto, combinar size-adjust com substituições de métricas de fonte possibilita fazer com que duas fontes correspondam na horizontal e na vertical.

É assim que size-adjust é usado nas 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 (explicado na próxima seção), o valor de size-adjust (e as substituições de 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 as substituições de métrica de tamanho e de fonte

Estas são as equações para calcular as substituições de size-adjust e 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 lacuna de linha) pode ser lida diretamente dos metadados da fonte da Web. No entanto, o valor de avgCharacterWidth precisa ser aproximado.

Aproximar a largura média de caracteres

Em geral, a largura média dos caracteres só pode ser aproximada, mas existem algumas situações em que isso pode ser calculado com exatidão, por exemplo, ao usar uma fonte monocromática ou quando o conteúdo de uma string de texto é conhecido com antecedência.

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

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

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

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

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

Como escolher uma abordagem

As duas abordagens discutidas neste artigo têm vantagens e desvantagens:

  • Usar as substituições de métrica de fonte por si só é uma boa abordagem se você está começando a otimizar suas fontes substitutas. Embora essa seja a mais simples das duas abordagens, ela normalmente é eficiente o suficiente para reduzir visivelmente a magnitude das mudanças de layout relacionadas à fonte.

  • Por outro lado, se você quer mais precisão e quer realizar um pouco mais de trabalho e testes, uma boa abordagem é incorporar size-adjust. Quando implementada corretamente, essa abordagem pode eliminar efetivamente as mudanças de layout relacionadas à fonte.

Como 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 ter em mente 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 nesse sistema operacional).

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

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

Pedido de feedback

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