Como atualizamos a web fonte dos PWAs do QuintoAndar

Fernando Rodrigues
Blog Técnico QuintoAndar
6 min readJan 14, 2021

Trabalho com web há dez anos e nesse período já desenvolvi dezenas de sites e aplicações com diferentes tipos de fonte. Há uns três meses, meu time decidiu que iria trabalhar em fundações do design system do QuintoAndar e o primeiro passo seria usarmos uma fonte proprietária. Até aí tudo bem. Eu achava que precisaria apenas alterar a propriedade font-family dos projetos da empresa e carregar os assets da nova fonte.

FOUT, FOFT, preload, variable font, e particularidades da propriedade font-display do CSS foram alguns dos termos que surgiram assim que comecei a estudar. Uma coisa ficou bem clara: eu precisava reciclar meu conhecimento em relação a como usar fontes na web.

Fonte proprietária do QuintoAndar

Vários PWAs, um design system e web performance

O QuintoAndar tem como objetivo ser a principal escolha para as pessoas quando o assunto é moradia. Para isso funcionar, temos aplicativos para diferentes tipos de usuários, como proprietários, inquilinos, corretores e fotógrafos. Hoje temos mais de vinte e oito PWAs (e contando).

A performance dessas aplicações é um requisito importante para o nosso negócio, uma vez que sempre buscamos fazer entregas que tenham uma experiência rápida para os usuários. E falando em entrega, temos um design system que está sendo desenvolvido há quase dois anos, e já está espalhado pelas aplicações.

Esse era nosso contexto, agora vamos às tecnologias.

Entregando fontes e estilos globais

Usamos CSS-in-JS para escrever nosso CSS, usando a biblioteca styled-components. Por meio dela, configuramos um tema, que nada mais é um objeto JavaScript com configurações de estilo através de nosso design system. Esse objeto é populado por um módulo JavaScript que é gerado pelo Style Dictionary, nossa ferramenta para gerenciar design tokens para diferentes plataformas — o QuintoAndar também tem apps nativos para iOS (Swift) e Android (Flutter).

Na prática, temos algo semelhante a isso:

import { elevations, palette, shape, typography } from '@quintoandar-design-system/tokens';export const theme = {
elevations,
palette,
shape,
typography,
};

Esse tema é utilizado pelas aplicações através do provider de nosso design system.

A escala tipográfica foi atualizada, assim como o peso e tamanho das fontes. Todas essas configurações foram feitas através de nosso pacote de tokens.

Para entregar o CSS com o @font-face, criamos uma biblioteca que entrega uma folha de estilo com os arquivos de fonte. Preferimos fazer dessa forma por dois motivos:

  • Aplicações e sites que não usam React podem instalar a fonte apenas usando CSS;
  • Self-host fonte é a melhor opção para entrega. Atualmente ferramentas de bundle como webpack possuem otimizações para essa técnica.

Além disso, há estilos globais necessários para a família da fonte funcionar, como estilo para elemento body. Para isso, criamos um componente React chamado <GlobalFontStyles/>, que é responsável por prover esse CSS.

No final, pra usar a fonte nossos desenvolvedores precisaram de dois passos:

  1. Atualizar a versão da biblioteca do design system;
  2. Instalar a biblioteca da fonte.
import '@quintoandar-typeface.css'; // CSS com font-face
import { GlobalFontStyle } from '@quintoandar-design-systen/globals'; // Estilos globais
const App = (props) => {
return (
<>
<GlobalFontStyle />
</>
);
};

Carregando e renderizando fontes de uma forma moderna

Como comentei no início do texto, meu conhecimento em relação a fonte se limitava a @font-face e as propriedades de fonte como font-family e font-size. Mas uma das primeiras descobertas em relação a performance foi sobre Variable Fonts.

Variable Fonts

Anteriormente precisávamos de um arquivo para cada estilo de fonte. Se usássemos três pesos diferentes, o usuário precisaria baixar três arquivos de fonte diferentes. Já uma variable font agrupa todos os estilos de fonte em um único arquivo. Veja o exemplo abaixo usando a variable font da famosa Roboto:

https://web.dev/variable-fonts

Para configurar esse tipo de fonte também usamos a propriedade @font-face, com a diferença que usamos woff2 supports variations para o format():

@supports (font-variation-settings: normal) {
@font-face {
font-family: 'Roboto Flex';
src: url('./fonts/RobotoFlex.woff2') format('woff2 supports variations'),
url('./fonts/RobotoFlex.woff2') format('truetype-variations');
font-weight: 100 1000;
font-stretch: 25% 151%;
}
}

A propriedade font-variation-settings nos provê um controle das configurações disponíveis da variable font através das letter axes disponíveis para serem usadas. Por padrão, temos os valores wght, wdth, slnt, ital e opsz, que respectivamente servem para customizar font-weight, font-stretch, font-style: oblique + angle, font-style: italic e font-optical-sizing. Mas também podemos utilizar axes customizados que podem ser disponibilizados por quem desenvolveu a fonte. No nosso caso, temos uma variação da fonte para títulos, e através da propriedade font-variation-settings controlamos qual família de fonte será usada:

/* QuintoAndarSans Body*/
body {
font-feature-settings: 'ss01' on;
}
/* QuintoAndarSans Title*/
h1, h2, h3,
h4, h5, h6 {
font-feature-settings: 'ss01' off;
}

Na prática, variable fonts ajudam muito em performance. Mas além delas, para ajudar em melhores resultados de carregamento é interessante fazer preload dos assets usando <link rel="preload">. Essa configuração irá fazer o request da fonte antes da construção do CSSOM.

Otimizando a forma de renderizar a fonte

A maioria dos navegadores modernos suportam a propriedade font-display, que determina como a fonte será renderizada. Para entender os valores que essa propriedade recebe, precisamos saber o que é a font display timeline. Ela é divida em três períodos que determinam como a fonte será renderizada.

  • Font block period: se a fonte não está disponível, isso não irá renderizar nada, e quando ela for baixada, ela aparecerá para o usuário.
  • Font swap period: enquanto a fonte não for renderizada, a fonte de fallback será mostrada.
  • Font failure period: é o momento que que a fonte não pode ser renderizada, e apenas o fallback é mostrado para o usuário.

No nosso caso, usamos font-display: swap, que renderiza a fonte de fallback até que a fonte customizada esteja disponível. O efeito colateral dessa estratégia é que em casos que a fonte demora para baixar, ocorrerá o que chamam de "flash of unstyled text" (FOUT).

https://web.dev/preload-optional-fonts

Desde a versão 83, o Google Chrome mudou a forma de como lida com o uso de font-display: optional. Nas versões antigas e em outros navegadores isso irá causar "flash of invisible text" (FOIT), ou seja, não irá renderizar o conteúdo até que a fonte esteja disponível. Mas a combinação dessa propriedade CSS com o preload dos arquivos de fonte, o primeiro paint já virá com a fonte correta.

Algo extremamente recomendado para otimizar é cachear os arquivos por um longo período e servir as fontes através de service worker.

Conclusão

Quando comecei a trabalhar ainda tinham sites que eram desenvolvidos com Flash para usar fontes customizadas. Depois o CSS3 nos deu o font-face e revolucionou a forma com que trabalhávamos. As especificações de fonte evoluíram absurdamente nos últimos dez anos.

A web não parou de evoluir e essa foi uma das principais características que me fizeram escolhe-la como ferramenta de trabalho. Na verdade fui eu quem parou de acompanhá-la e essa foi uma das grandes lições que tive no último ano: nunca parar de evoluir com a web.

Quer trabalhar em um lugar onde você tem tempo de estudar e entregar produtos com qualidade? Quer trabalhar em um lugar com desafios em escala e muitas pessoas brilhantes pra te ajudar a resolver eles e aprender sobre? Vem pro QuintoAndar!

--

--