Todos os artigos

As fontes do Windows 95 na web moderna

3 min de leitura

Tem uma fonte que qualquer pessoa que tocou num computador nos anos 90 reconhece na hora.

MS Sans Serif. Aquela tipografia pequenininha, quadrada, com pixels visíveis, que aparecia em tudo no Windows 95: menus, botões, caixas de diálogo, barras de título.

O React95 já tinha os componentes e os estilos. As fontes, não. No browser, saíam as do sistema. Sentia que faltava alguma coisa. O React95 foi feito pra ser pixel perfect, e usar a fonte errada quebrava isso.

Existem várias fontes por aí que se parecem com a MS Sans Serif. A W95FA é uma delas, feita pra nos lembrar aquela época. E elas funcionam, de longe. De perto, não são a mesma. Não são pixel perfect.

Eu queria exatamente aquela.

O problema

As fontes originais do Windows 95 vivem dentro de arquivos .FON, um formato binário da Microsoft de 1987, feito pra fontes de bitmap na época do DOS. Não tem caminho direto entre um .FON e um @font-face moderno. Ninguém vai simplesmente “importar” isso no CSS.

Então a pergunta virou: será que dá?

A extração

A resposta foi Python. Não é a linguagem que eu uso no dia a dia, mas era o que eu precisava. Com um empurrãozinho da IA pra não travar nas partes que não dominava, consegui seguir em frente.

Tem uma biblioteca chamada monobit que lê arquivos .FON antigos e extrai os dados dos glifos. A partir daí, fontTools reconstrói cada tamanho como uma fonte TTF de verdade, com as métricas corretas e a tabela gasp configurada pra o browser não aplicar antialiasing e estragar os pixels. Depois, brotli comprime em WOFF2 e embute o resultado como base64 direto no CSS.

Cada fonte, cada tamanho, virou um arquivo CSS independente com o @font-face já pronto.

A parte estranha de fontes bitmap

Fontes vetoriais escalam: você define font-size: 32px e a fonte se adapta. Fontes bitmap não funcionam assim. Cada tamanho é um conjunto fixo de pixels que se você aumenta, os pixels ficam borrados, fora do lugar, errados. Ou você renderiza na resolução certa ou não.

Isso significa que R95 Sans Serif 14pt e R95 Sans Serif 18pt não são tamanhos da mesma família. São famílias diferentes. Cada uma tem seu nome, sua altura nativa em pixels, e precisa ser usada na escala certa.

body {
font-family: 'R95 Sans Serif 14pt';
font-size: 24px; /* altura nativa do 14pt em 96 dpi */
}

É contraintuitivo até fazer sentido: cada tamanho é uma fonte diferente porque cada pixel foi desenhado à mão para aquela escala.

O pacote

O resultado foi @react95/fonts: quatro variantes, MS Sans Serif e MS Serif, em 96 dpi e 120 dpi, com seis tamanhos cada. Vinte e oito arquivos CSS gerados automaticamente pelo script Python, com base64 embutido, sem requisições extras.

npm install @react95/fonts

E você escolhe o quanto quer importar:

// Tudo
import '@react95/fonts';
// Só uma variante
import '@react95/fonts/sans-serif';
// Um tamanho específico
import '@react95/fonts/sans-serif/14pt';

O código está no GitHub. O pacote no npm. E se quiser ver as fontes antes de instalar, tem uma demo feita com o próprio React95.

Experimente aqui:

R95 Sans Serif 8pt
R95 Sans Serif 10pt
R95 Sans Serif 12pt
R95 Sans Serif 14pt
R95 Sans Serif 18pt
R95 Sans Serif 24pt
R95 Sans Serif HiRes 8pt
R95 Sans Serif HiRes 10pt
R95 Sans Serif HiRes 12pt
R95 Sans Serif HiRes 14pt
R95 Sans Serif HiRes 18pt
R95 Sans Serif HiRes 24pt
R95 Serif 8pt
R95 Serif 10pt
R95 Serif 12pt
R95 Serif 14pt
R95 Serif 18pt
R95 Serif 24pt
R95 Serif HiRes 8pt
R95 Serif HiRes 10pt
R95 Serif HiRes 12pt
R95 Serif HiRes 14pt
R95 Serif HiRes 18pt
R95 Serif HiRes 24pt
Config

Utilidade de mercado: nenhuma

Ninguém precisa da MS Sans Serif pra construir um produto. Mas tem uma diferença entre “parecido” e “correto”, e essa diferença me incomodava.

O React95 existe porque eu quis aprender fazendo algo divertido. O @react95/fonts existe pelo mesmo motivo: a fonte certa, no pixel certo. E às vezes isso vira um pacote que outras pessoas usam.