Tipografia fluida
Tags: css, typography, webdev, braziliandevs
Published: 2023-09-11 15:14:43

*Foto por Ross Findon no Unsplash*
> You can access this article in English [here](https://dev.to/marcelluscaio/fluid-typography-1mfl)
> Você pode acessar este artigo em inglês [aqui](https://dev.to/marcelluscaio/fluid-typography-1mfl)

## Promessa é dívida

Alguns dias atrás [escrevi sobre algumas dicas de tipografia](https://dev.to/marcelluscaio/usar-rem-nao-torna-seu-site-responsivo-entenda-por-que-559e). Vimos a importância de usarmos a unidade REM, e como tornar responsivas nossas fontes usando Media Queries. Com isso você já consegue fazer projetos para a web impecáveis do ponto de vista do tamanho de fontes. Mas eu prometi que iria falar sobre como tornar as fontes responsivas sem usar Media Queries, e promessa é dívida. Vamos lá!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hplee4zelqbexw0m8xef.jpg)

## Os limites das Media Queries

Quando adaptamos o tamanho de fontes usando media queries, nossas fontes ficam com o mesmo tamanho até atingir o ponto de quebra, e só aí mudam. 

Abra o codepen abaixo e mexa na largura da tela para ver a mudança repentina no tamanho da fonte.

{% codepen https://codepen.io/marcelluscaio/pen/XWopvde %}
[Abra o codepen em outra aba.]( https://codepen.io/marcelluscaio/pen/XWopvde)

Usando a  técnica de tipografia fluida, nossa fonte vai sempre se ajustar ao tamanho da tela. A cada pixel que a tela aumenta, há um incremento nas fontes.

“Caio, que bruxaria é essa? Como isso é possível?”

Não é bruxaria, mas uma função poderosíssima do CSS: o clamp().


## Conhecendo o clamp()

Com o clamp a gente pode definir um valor mínimo, um valor ideal, e um valor máximo. 

Digamos que queremos que nossa fonte seja 16px em uma largura de tela de 320px, e que seja de 32px numa largura de tela de 1920px. Nosso clamp ficaria mais ou menos assim:

```css
clamp(1rem, valor ideal, 2rem);

/*
Notou que estamos usando REM, certo? 
Nada de PX para fontes, lembra?
*/
```

E para o valor ideal? Bem, como a gente quer que nossa fonte se adapte ao tamanho da tela, vamos aplicar uma das viewport units, o VW. 100vw é o tamanho da tela. 1vw é 1% da largura da tela. Numa tela de 320px, 100vw são 320px, 1vw é igual a 3.2px.

Vamos usar temporariamente o valor de 5vw.

```css
clamp(1rem, 5vw, 2rem)
```

Com isso, nossa fonte ainda tem aqueles limites mínimo e máximo de 16px e 32px (pela fonte padrão do navegador), mas com o 5vw como valor ideal ela vai sempre tentar ter 5vw de tamanho.

Vejamos alguns exemplos:

> Em uma tela de 300px: 5vw seria 15px. 15px é menor que 16px – nossa fonte mínima. Nesse caso, a fonte seria 16px.

> Em uma tela de 320px: 5vw seria 16px. A fonte usada seria 16px.

> Em uma tela de 500px: 5vw seria 25px. 25px é maior que 16px, e é menor que o limite máximo de 32px. A fonte usada seria 25px.

> Em uma tela de 1000px: 5vw seria 50px. Como esse valor é maior que o nosso limite, a fonte utilizada seria de 32px.

Veja esse exemplo aplicado abaixo:

{% codepen https://codepen.io/marcelluscaio/pen/eYbvYyZ %}

[Abra o codepen em outra aba.]( https://codepen.io/marcelluscaio/pen/eYbvYyZ)


### Nem tudo são flores

Temos dois problema aqui: 

1)	Nossa fonte está crescendo rápido demais nesse exemplo. Ela atingiu o nosso limite em 640px de largura de tela, e nós queríamos que ela variasse de forma fluida até 1920px. Ela ficaria estática por 1280px! 

2)	Usar uma fonte baseada somente em unidades de viewport traz um problema para a acessibilidade. Experimente voltar no codepen anterior, e dê zoom na tela. A pessoa usuária não consegue dar zoom na fonte, que fica congelada já que está baseada no tamanho da tela. Veja que o texto no centro da tela não altera de tamanho, enquando o contador de tamanho de tela e fonte no canto superior esquerdo aumenta. 


## Usando VW + REM

Uma técnica que ajuda com esses dois problema é definir o valor ideal, do meio do clamp, não apenas em vw, mas em um cálculo da soma de vw com rem.

Vamos usar os seguintes valores:

```css
clamp(1rem, .8rem + 1vw, 2rem)
```

Veja no exemplo abaixo que a fonte começa a crescer exatamente depois de 320px, e para logo antes de 1920px!

{% codepen https://codepen.io/marcelluscaio/pen/MWZpYwJ %}

[Abra o codepen em outra aba.]( https://codepen.io/marcelluscaio/pen/MWZpYwJ)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xnd9qdhaa3mecrjtb28n.gif)


“Caio você é um gênio! Como você chegou nesse valor?”

Odeio desapontar você, querida pessoa leitora, mas eu não fiz essa conta de cabeça! Existe uma fórmula para calcular esse valor ideal, e toda a explicação disso vai estar em um dos artigos que vou deixar nas referências. Nesse exemplo e no dia-a-dia eu uso uma ferramenta que calcula isso pra mim.

[Você pode acessar essa ferramenta aqui.](https://utopia.fyi/type/calculator)


### O Fluid Type Calculator


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vi7mm8mskhoe21dw802x.png)

Aqui a gente pode definir a largura mínima e máxima de tela e o tamanho mínimo e máximo de fonte - ignore por hora a opção de Type Scale (Escala de tipografia).

A ferramenta já dá os valores em clamp para você. Daí é só colocar no seu código e correr pro abraço.


### Lidando com mais de um tamanho ao mesmo tempo

> “Caio, eu nunca trabalhei em um projeto com um tamanho de fonte só!”

Eu sei, eu sei. O exemplo com só um tamanho de fonte era pra facilitar o entendimento. Vamos aplicar essa lógica para aquele nosso primeiro exemplo, das fontes com Media Queries?

Lá tínhamos o seguinte modelo de fonte:

Nível 1 -> 16px até 18px;

Nível 2 -> 20px até 24px;

Nível 3 -> 25px até 32px;

Nível 4 -> 31px até 42px;


Daí é só a gente entrar naquela nossa calculadora e fazer cada um desses intervalos!

Antes tínhamos:

```css
:root{
  --fs-1: 1.125rem;
  --fs-2: 1.5rem;
  --fs-3: 2rem;
  --fs-4: 2.625rem
}

@media (max-width: 40em){
  :root{
    --fs-1: 1rem;
    --fs-2: 1.25rem;
    --fs-3: 1.5625rem;
    --fs-4: 1.9375rem
  }
}
```

O resultado é esse daqui:

```css
:root{
  --fs-1: clamp(1.00rem, calc(0.98rem + 0.13vw), 1.13rem);;
  --fs-2: clamp(1.25rem, calc(1.20rem + 0.25vw), 1.50rem);
  --fs-3: clamp(1.56rem, calc(1.48rem + 0.44vw), 2.00rem);
  --fs-4: clamp(1.95rem, calc(1.81rem + 0.71vw), 2.66rem)
}
```

Veja no exemplo abaixo:

{% codepen https://codepen.io/marcelluscaio/pen/VwqpYdO %}

[Abra o codepen em outra aba.]( https://codepen.io/marcelluscaio/pen/VwqpYdO)



## E aquele lance de Type scale?

Nós, como desenvolvedores, muitas vezes não participamos do processo de escolha do tamanho de fontes. Designers costumam estar à frente dessa decisão. “E como eles chegam naqueles valores?”, você pode estar se perguntando.

Isso é uma ciência à parte. Há diferentes sistemas: o 4-point grid, o 8-point grid, o Material Design do Google, e muitos outros. E o uso de nenhum desses sistemas prescinde do olhar treinado dos profissionais de design: sistemas não são mágica, e muitas vezes necessitam de adaptações.

Um desses sistemas é a tipografia com escala modular. Nesse sistema, nós partimos de um tamanho de fonte, e aumentamos ou diminuímos a partir de um fator de multiplicação. Por exemplo, digamos que nossa menor fonte seja 10px, e que o fator de multiplicação seja 2. Nosso sistema de fontes poderia ter os seguintes valores: 10px, 20px, 40px, 80px, etc. Esse exemplo é um exagero, apenas com fins didáticos, claro.

Essa metodologia imprime uma maior objetividade na escolha dos tamanhos de fonte, e ajuda a hierarquia da nossa tipografia a ser mais consistente. 

O campo Type Scale da nossa calculadora ajuda a gerar fontes usando esse tipo de metodologia. Digamos que eu tenha um projeto com 4 níveis de fonte (4 tamanhos diferentes), e o menor deles deve ser 14px em celulares e 20px em monitores.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hu3vxyobcl6yq7zo223j.png)

Aqui estou aplicando uma taxa de crescimento de 1.25 em telas de 320px, enquanto aplico uma taxa de crescimento de 1.414 em telas de 1900px. O resultado é o seguinte:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ogilib8u6vn0yeoqe2a.png)

Note que os tamanhos de fonte crescem bem mais rápido na tela de 1900px, porque a taxa que usamos é maior. Convido você a ler os excelentes artigos sobre escalas modulares em tipografia que estarão nas referências deste artigo para entender melhor em que situações escolher qual taxa para a sua escala. Encorajo ainda a gerar e testar diferentes escalas e comparar o resultado. O que acontece quando a a taxa da escala em telas grandes é maior que em telas pequenas? O que acontece quando a taxa é a mesma? E quando é menor?

## Conclusão

Aprendemos como aplicar a técnica de tipografia fluida usando CSS. A tipografia fluida é uma solução elegante que traz integridade visual para o seu projeto nas mais diversas telas. 

É sempre importante lembrar que a acessibilidade é uma prioridade. Para garantir que seu site está acessível, faça sempre testes com zoom em 200%.



## Referências

Kevin Powell - Simple solutions to responsive typography
https://www.youtube.com/watch?v=wARbgs5Fmuw

Modern Fluid Typography Using CSS Clamp
https://www.smashingmagazine.com/2022/01/modern-fluid-typography-css-clamp/

Generating `font-size` CSS Rules and Creating a Fluid Type Scale
https://moderncss.dev/generating-font-size-css-rules-and-creating-a-fluid-type-scale/

Responsive Type and Zoom
https://adrianroselli.com/2019/12/responsive-type-and-zoom.html

Resize text
https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-scale.html

Should I change the default HTML font-size to 62.5%?
https://fedmentor.dev/posts/rem-html-font-size-hack/

4-Point Grid System for more consistent interface design
https://medium.com/@aratidube12lns/4-point-grid-system-for-more-consistent-interface-design-efea81dea3f3

More Meaningful Typography
https://alistapart.com/article/more-meaningful-typography/

Um guia prático para criar um tipo de escala modular para suas interfaces
https://www.ux-republic.com/pt/guia-pr%C3%A1tico-para-criar-um-tipo-de-escala-modular-para-suas-interfaces/