Tipografia fluida moderna usando braçadeira CSS
Publicados: 2022-03-10 O conceito de tipografia fluida no desenvolvimento web está presente há anos, e os desenvolvedores tiveram que contar com várias soluções alternativas para fazê-lo funcionar no navegador. Com a nova função CSS clamp
, a criação de tipografia fluida nunca foi tão simples.
Normalmente, quando implementamos a tipografia responsiva , os valores mudam em pontos de interrupção específicos. Eles são explicitamente definidos. Portanto, os designers geralmente fornecem valores tipográficos (tamanhos de fonte, alturas de linha, espaçamento entre letras, etc.) para dois, três ou até mais tamanhos de tela, e os desenvolvedores geralmente implementam esses requisitos adicionando consultas de mídia para segmentar pontos de interrupção específicos.
Embora os elementos de tipografia possam parecer tão bons quanto nos designs, esse pode não ser o caso de alguns elementos em larguras de viewport próximas aos pontos de interrupção. Como já sabemos, existem muitos dispositivos e tamanhos de tela diferentes disponíveis para os usuários além dos abordados no design. Adicionar mais pontos de interrupção e substituições de estilo pode corrigir o problema, mas corremos o risco de aumentar a complexidade do código, criando mais casos extremos e tornando o código menos claro e sustentável.
A tipografia fluida é dimensionada suavemente entre o valor mínimo e máximo, dependendo da largura da janela de visualização. Geralmente começa com um valor mínimo e mantém o valor constante até um ponto específico da largura da tela em que começa a aumentar. Quando atinge um valor máximo em outra largura de tela, mantém esse valor máximo a partir daí. Veremos neste artigo que a tipografia fluida também pode fluir na ordem inversa — comece com um valor máximo e termine com um valor mínimo.
Essa abordagem reduz ou elimina o ajuste fino para pontos de interrupção específicos e outros casos extremos. Embora seja usado principalmente em tipografia, essa abordagem de dimensionamento fluido também funciona para margem, preenchimento, lacuna etc.
Observe como no exemplo a seguir, o texto do título é dimensionado suavemente e como ele fica bem em qualquer largura de viewport. Além disso, observe como o conteúdo ainda mantém a tipografia responsiva e o valor muda apenas em um ponto de interrupção.
Embora a tipografia fluida resolva os problemas mencionados acima, ela não é ideal para todos os cenários, e a tipografia fluida não deve ser tratada como um substituto para a tipografia responsiva . Cada um tem seu próprio conjunto de práticas recomendadas e casos de uso adequados e abordaremos isso mais adiante neste artigo.
Neste artigo, vamos mergulhar profundamente na tipografia fluida e verificar várias abordagens que os desenvolvedores usaram no passado. Também abordaremos a função de clamp
do CSS e como ela simplificou a implementação da tipografia fluida, e aprenderemos como ajustar os parâmetros da função de clamp
para controlar os pontos inicial e final do comportamento do fluido. Também abordaremos questões de acessibilidade, a maioria das quais pode ser resolvida hoje, e um importante problema de acessibilidade que ainda não podemos corrigir.
Primeiras tentativas de tipografia fluida
Como desenvolvedores, geralmente usamos JavaScript para complementar os recursos CSS ausentes até que sejam desenvolvidos e suportados nos principais navegadores. Nos primeiros dias do web design responsivo, bibliotecas JavaScript como FlowType.JS foram usadas para obter tipografia fluida.
A primeira implementação CSS real de tipografia fluida veio com a introdução de CSS calc
e viewport units ( vw
e vh
).
/* Fixed minimum value below the minimum breakpoint */ .fluid { font-size: 32px; } /* Fluid value from 568px to 768px viewport width */ @media screen and (min-width: 568px) { .fluid { font-size: calc(32px + 16 * ((100vw - 568px) / (768 - 568)); } } /* Fixed maximum value above the maximum breakpoint */ @media screen and (min-width: 768px) { .fluid { font-size: 48px; } }
Este trecho parece um pouco complexo e há muitos números envolvidos no cálculo. Então, vamos dividir isso em segmentos e ter uma visão geral de alto nível do que está acontecendo. Vamos nos concentrar em seletores e consultas de mídia para ver os casos que eles cobrem.
.fluid { /* Min value */ } @media screen and (min-width: [breakpoint-min]) { .fluid { /* Preferred value between the minimum and maximum bound */ } @media screen and (min-width: [breakpoint-max]) { /* Max value */ }
Na abordagem mobile-first, o primeiro seletor fixa o valor em um limite mínimo. A primeira consulta de mídia trata do comportamento fluido entre os dois pontos de interrupção. O ponto de interrupção final fixa o valor em um limite máximo. Agora que sabemos o que cada seletor e consulta de mídia faz, vamos ver como os limites mínimo e máximo são aplicados e como o valor fluido está sendo calculado.
.fluid { font-size: [value-min]; } @media (min-width: [breakpoint-min]) { .fluid { font-size: calc([value-min] + ([value-max] - [value-min]) * ((100vw - [breakpoint-min]) / ([breakpoint-max] - [breakpoint-min]))); } } @media (min-width: [breakpoint-max]) { .fluid { font-size: [value-max] } }
Isso é muito código clichê para realizar uma tarefa muito simples de fixar um valor entre os limites mínimo e máximo e adicionar um comportamento fluido entre dois pontos de interrupção.
Apesar da quantidade de clichê necessária, essa abordagem se tornou tão popular para lidar com dimensionamento de fluidos em geral, que ficou claro que era necessária uma abordagem mais simplificada. É aqui que entra a função de fixação CSS.
Função de clamp
CSS
A função de clamp
CSS aceita três valores — um limite mínimo, um valor preferencial e um limite máximo , e fixa o valor atual entre esses limites. O valor preferencial é usado para determinar o valor entre o limite. O valor preferencial geralmente inclui unidades de janela de visualização, porcentagens ou outras unidades relativas para obter o efeito fluido. Esta é uma função tão robusta e flexível que, juntamente com os valores fixos, pode aceitar até mesmo funções e expressões matemáticas e valores da função attr
.
clamp([value-min], [value-preferred], [value-max]);
Esta função pode ser aplicada a qualquer atributo que aceite um tipo de valor válido como comprimento, frequência, tempo, ângulo, porcentagem, número e outros, para que possa ser usada além de tipografia e dimensionamento.
O suporte do navegador para a função de clamp
está acima de 90% no momento da redação deste artigo, por isso já é bem suportado. Para navegadores de desktop não suportados, como o Internet Explorer, é suficiente fornecer um valor de fallback, pois os navegadores não suportados ignorarão toda a expressão font-size
se não puderem analisar a função clamp
.
font-size: [value-fallback]; /* Fallback value */ font-size: clamp([value-min], [value-preferred], [value-max]);
Tipografia fluida com clamp
CSS
Vamos usar a função de clamp
CSS e preenchê-la com os seguintes valores:
- Valor mínimo — igual ao tamanho mínimo da fonte.
- Valor máximo — igual ao tamanho máximo da fonte.
- Valor preferencial — determina como a tipografia fluida é dimensionada — pontos iniciais e finais do comportamento fluido e velocidade de mudança. Esse valor dependerá do tamanho da janela de visualização, portanto, usaremos a unidade de largura da janela de visualização
vw
.
Vamos dar uma olhada no exemplo a seguir e definir o tamanho da fonte para ter um valor entre 32px
e 48px
. O font-size
seguir tem um mínimo definido de 32px
e um máximo de 48px
. O valor atual é determinado pela unidade de largura da janela de visualização ou, mais precisamente, 4%
da largura da janela de visualização atual se esse valor estiver entre o limite mínimo e máximo.
font-size: clamp(32px, 4vw, 48px);
Vamos dar uma olhada rápida em qual valor será aplicado para este exemplo dependendo da largura da janela de visualização, para que possamos ter uma boa noção de como a função de fixação CSS funciona.
Largura da janela de visualização (px) | Valor preferencial (px) | Valor aplicado (px) |
---|---|---|
500 | 20 | 32 (apertado a um limite mínimo) |
900 | 36 | 36 (valor preferencial entre os limites) |
1400 | 56 | 48 (apertado a um limite máximo) |
Podemos notar dois problemas com este valor da função clamp:
- Os valores de pixel para min e max não são acessíveis.
Os limites mínimo e máximo são expressos com valores de pixel, portanto, eles não serão dimensionados se um usuário alterar o tamanho de fonte preferido. - O valor da viewport para o valor preferencial não está acessível.
Igual ao caso anterior. Este valor depende exclusivamente da largura da janela de visualização e não leva em consideração as preferências do usuário. - O valor preferencial não é claro.
Estamos usando4vw
que pode parecer um número mágico a princípio. Precisamos saber quando o comportamento fluido começa e termina para que possamos sincronizar várias alterações de tamanho de fonte fluida.
Podemos resolver facilmente o primeiro problema convertendo valores px
em valores rem
para limites mínimos e máximos, dividindo os valores px
por 16 (tamanho padrão da fonte do navegador). Ao fazer isso, os valores mínimo e máximo se adaptarão às preferências do navegador do usuário.
font-size: clamp(2rem, 4vw, 3rem);
Precisamos adotar uma abordagem diferente com o valor preferencial, pois esse valor precisa responder ao tamanho da janela de visualização. No entanto, podemos misturar facilmente o valor rem
relativo transformando-o em uma expressão matemática.
font-size: clamp(2rem, 4vw + 1rem, 3rem);
Observe que esta não é uma solução infalível para todos os problemas de acessibilidade , portanto, ainda é importante testar se a tipografia fluida pode ser ampliada o suficiente e se responde bem o suficiente às preferências de acessibilidade do usuário. Abordaremos essas questões mais adiante.
No entanto, ainda não sabemos como obtivemos o valor preferencial do exemplo ( 4vw + 1rem
) para obter o comportamento de fluido necessário, então vamos dar uma olhada em como podemos ajustar o valor preferencial e entender completamente a matemática por trás dele .
Função de dimensionamento de fluido
O valor preferencial afeta o comportamento da função de tipografia fluida . Mais precisamente, podemos alterar em quais pontos de largura de viewport o valor mínimo começa a mudar e em qual ponto de largura de viewport ele atinge o valor máximo.
Por exemplo, podemos querer que o comportamento fluido comece em 1200px
e termine em 800px
da largura da janela de visualização. Observe que limites mínimos e máximos diferentes exigem valores preferenciais diferentes (valor da janela de visualização e tamanho relativo) para manter as várias tipografias fluidas em sincronia.
Por exemplo, geralmente não queremos que um comportamento fluido ocorra entre 1200px
e 800px
da largura da janela de visualização e outro ocorra entre 1000px
e 750px
da largura da janela de visualização. Isso pode levar a inconsistências de dimensionamento, como no exemplo a seguir.
Para evitar esse problema, precisamos descobrir como o valor preferencial é calculado e atribuir a janela de visualização adequada e os valores relativos ao valor preferencial da função clamp.
Vamos descobrir uma função que é usada para calculá-lo.
font-size: clamp([min]rem, [v]vw + [r]rem, [max]rem);
$$y=\frac{v}{100}*x + r$$
- x — valor atual da largura da janela de visualização (
px
). - y — tamanho de fonte fluido resultante para um valor de largura de janela de visualização atual x (
px
). - v — valor da largura da janela de visualização que afeta a taxa de alteração do valor do fluido (
vw
). - r — tamanho relativo igual ao tamanho da fonte do navegador. O valor padrão é
16px
.
Com esta função, podemos calcular facilmente os pontos inicial e final do comportamento do fluido. Para o nosso exemplo, o valor mínimo de 2rem
( 32px
) é constante até a largura da janela de visualização de 400px
.
$$32=\frac{4}{100}*x + 16$$
$$16=\frac{1}{25}*x$$
$$x=400$$
Podemos aplicar a mesma função para o valor máximo e ver que ela atinge um valor máximo de 3rem
( 48px
) em uma largura de viewport de 800px
.
O objetivo deste exemplo foi apenas demonstrar como o valor preferencial afeta o comportamento da tipografia fluida. Vamos usar a mesma função para um cenário um pouco mais realista e resolver um exemplo mais prático do mundo real. Criaremos tipografia fluida acessível com base nos tamanhos de fonte necessários e pontos específicos onde queremos que o comportamento fluido ocorra.
Calculando parâmetros de valor preferidos com base em pontos iniciais e finais específicos
Vamos dar uma olhada em um exemplo prático que aparece frequentemente em cenários do mundo real. Os designers nos forneceram os tamanhos de fonte e pontos de interrupção que, como desenvolvedores, precisamos para implementar a tipografia fluida com os seguintes parâmetros:
- O tamanho mínimo da fonte é
36px
(y1) - O tamanho máximo da fonte é
52px
(y2) - O valor mínimo deve terminar na largura da janela de visualização de
600px
(x1) - O valor máximo deve começar na largura da janela de visualização de
1400px
(x2)
Vamos pegar esses valores e adicioná-los à função de dimensionamento de fluidos que discutimos anteriormente.
$$y=\frac{v}{100} \cdot x + r$$
Acabamos com duas equações com dois parâmetros que precisamos calcular — valor da largura da janela de visualização v
e tamanho relativo r
.
$$(1)\;\;\; y_1=\frac{v}{100} \cdot x_1 + r$$
$$(2) \;\;\; y_2 =\frac{v}{100} \cdot x_2 + r$$
Podemos pegar a primeira equação e transformá-la na seguinte expressão que podemos usar.
$$(1) \;\;\; r=y_1 - \frac{v}{100} \cdot x_1$$
Podemos substituir r
na segunda equação por esta expressão e obter a função para calcular v
.
$$v=\frac{100 \cdot (y_2-y_1)}{x_2 - x_1}$$
$$v=\frac{100\cdot (52-36)}{1400 - 600}$$
$$v=2$$
Obtemos o valor de largura da janela de visualização 2vw
. De maneira semelhante, podemos isolar r
e calculá-lo usando os parâmetros disponíveis.
$$r=\frac{x_1y_2 - x_2y_1}{x_1 - x_2}$$
$$r=\frac{600 \cdot 52 - 1400 \cdot 36}{600 - 1400}$$
$$r=24$$
Nota : Este valor está em pixels e o valor relativo precisa ser expresso em rem
, então dividimos o valor do pixel por 16
e terminamos com 1.5rem
.
Também precisamos converter o limite mínimo de 36px
e o limite máximo de 52px
para rem
e adicionar todos os valores à função CSS clamp
.
font-size: clamp(2.25rem, 2vw + 1.5rem, 3.25rem);
Podemos plotar esta função para confirmar que os valores calculados estão corretos.
Para resumir, podemos usar as duas funções a seguir para calcular os parâmetros de valor preferido v
(expresso em vw
) e r
(expresso em rem
) a partir de tamanhos de fonte e pontos de largura da janela de visualização.
$$v=\frac{100 \cdot (y_2-y_1)}{x_2 - x_1}$$
$$r=\frac{x_1y_2 - x_2y_1}{x_1 - x_2}$$
Agora que entendemos completamente como funciona a função clamp
e como o valor preferencial está sendo calculado, podemos facilmente criar tipografia fluida consistente e acessível em nossos projetos e evitar as armadilhas mencionadas acima.
Usando o valor negativo da janela de visualização para dimensionamento de fluido
Também podemos aumentar o tamanho à medida que o tamanho da janela de visualização diminui usando um valor negativo para o valor da janela de visualização. O valor negativo da janela de visualização reverterá o comportamento fluido padrão. Também precisamos ajustar o tamanho relativo para que o comportamento do fluido comece e termine em determinados pontos, resolvendo as duas equações acima mencionadas do exemplo anterior.
font-size: clamp(3rem, -4vw + 6rem, 4.5rem);
Eu não usei essa configuração invertida em meus projetos, mas você pode achar interessante se você encontrar esse requisito em seu projeto ou design.
Ferramenta de visualização de tipografia fluida
Enquanto estava trabalhando em um projeto, tive que criar várias configurações diferentes de tipografia fluida. Eu estava testando as configurações no navegador e tive a ideia de criar uma ferramenta que ajudasse os desenvolvedores a visualizar e ajustar o comportamento da tipografia fluida. Eu me inspirei em uma das demos do curso “CSS para desenvolvedores JS” de Josh W. Comeau e criei a Modern Fluid Typography Tool.
Os desenvolvedores podem usar essa ferramenta para criar e ajustar trechos de código de tipografia fluida e visualizar o comportamento fluido para manter várias instâncias sincronizadas. A ferramenta também pode gerar um link para a configuração, para que os desenvolvedores possam incluir o link nos comentários do código ou na documentação para que outros possam verificar facilmente o comportamento do dimensionamento fluido.
Este projeto é gratuito e de código aberto, portanto, sinta-se à vontade para relatar quaisquer bugs e contribuir. Fico feliz em ouvir seus pensamentos e solicitações de recursos!
Preocupações de acessibilidade
É importante reiterar que o uso de valores rem
não torna a tipografia fluida automaticamente acessível para todos os usuários, apenas permite que os tamanhos de fonte respondam às preferências de fonte do usuário. O uso da função de clamp
CSS em combinação com as unidades de viewport para obter o dimensionamento fluido apresenta outro conjunto de desvantagens que precisamos considerar.
Adrian Roselli testou e documentou esses problemas extensivamente em sua postagem no blog.
“Quando você usa unidadesvw
ou limita o tamanho do texto comclamp()
, há uma chance de um usuário não conseguir dimensionar o texto para 200% do tamanho original. Se isso acontecer, é uma falha do WCAG em 1.4.4 Redimensionar texto (AA), portanto, certifique-se de testar os resultados com zoom.”
— Adrian Roselli
Eu queria resolver esse problema desde o início usando JavaScript para detectar quando o evento de zoom ocorre e aplicar uma classe que substituirá o dimensionamento fluido por um valor rem
regular.
/* Apply fluid typography for default zoom level (not zoomed) */ .title { font-size: clamp(2rem, 4vw + 1rem, 3rem); } /* Revert to responsive typography if zoom is active */ body.zoom-active .title { font-size: 2rem; } @media screen and (min-width: 768px) { body.zoom-active .title { font-size: 3rem; } }
Você pode se surpreender ao descobrir que não podemos detectar de forma confiável o evento de zoom usando JavaScript, como podemos detectar qualquer outro evento de viewport regular, como redimensionar.
Existe a especificação da API Visual Viewport com um sólido suporte de navegador de 92% no momento da redação deste artigo, mas o valor de escala (nível de zoom) simplesmente não funciona - ele retorna o mesmo valor, independentemente do valor de zoom (escala). Sem mencionar que não há documentação, exemplos de trabalho ou casos de uso disponíveis. Isso é um pouco estranho, considerando que essa API tem um suporte tão sólido ao navegador. Existem algumas soluções alternativas, mas também não são totalmente confiáveis e não podem detectar se a página foi ampliada quando é carregada pela primeira vez, somente após a ocorrência do evento.
Se a API Visual Viewport funcionasse como pretendido, poderíamos facilmente alternar uma classe CSS no evento de zoom.
/* This code won't work because visualViewport.scale is buggy * and always returns the same value. This might be fixed in the future. */ function checkZoomLevel() { if (window.visualViewport.scale === 1) { document.body.classList.remove("zoom-active"); } else { document.body.classList.add("zoom-active"); } } window.addEventListener("resize", checkZoomLevel);
É lamentável que, ao aplicar o dimensionamento fluido, estejamos arriscando tornar o conteúdo inacessível para alguns usuários que usam a funcionalidade de zoom durante a navegação. Até que possamos criar um fallback confiável e mais acessível para tipografia fluida, certifique-se de usar dimensionamento fluido com moderação e teste se os níveis de zoom estão de acordo com as Diretrizes de acessibilidade de conteúdo da Web (WCAG).
Casos de uso recomendados
A tipografia fluida funciona melhor para elementos de texto grandes e proeminentes com uma diferença maior entre o tamanho mínimo e máximo. Títulos grandes parecerão mais chocantes e fora de lugar em viewports menores se não forem dimensionados adequadamente.
O dimensionamento fluido também é recomendado para os casos em que precisamos manter um dimensionamento consistente.
Elise Hein chegou a uma conclusão semelhante em seu artigo sobre as melhores práticas de tipografia fluida.
“Eu tentei e não consegui encontrar muitas áreas específicas onde a tipografia relativa à janela de visualização supera o dimensionamento baseado em ponto de interrupção em termos de legibilidade. Aqui estão dois: definir o texto de exibição e manter a medida consistente .”
— Elise Hein
A tipografia fluida não é tão eficaz ou útil se a diferença entre o mínimo e o máximo for de apenas alguns pixels , como é o caso usual com o corpo do texto. O corpo do texto com uma pequena diferença entre os tamanhos de fonte mínimo e máximo não parecerá deslocado em nenhuma largura de janela de visualização, como é o caso de tamanhos de fonte maiores. Para esses casos, é recomendável usar tipografia responsiva regular com pontos de interrupção.
Conclusão
A tipografia fluida não deve servir como um substituto para a tipografia responsiva, mas sim como um aprimoramento para casos de uso específicos. Devemos usar tipografia fluida para dimensionar suavemente o texto com uma diferença maior entre o tamanho mínimo e o máximo e manter um dimensionamento consistente.
Ao usar vários elementos de tipografia fluida com a função de clamp
CSS, devemos garantir que a escala fluida esteja sincronizada. Podemos fazer isso calculando a largura da janela de visualização e o valor relativo e usando-os como valores preferenciais na função de clamp
CSS. Também devemos ter em mente o uso de unidades relativas como unidade rem para que a tipografia fluida se adapte às preferências de tamanho de fonte do usuário.
Também vimos como a tipografia fluida pode limitar os recursos de zoom do usuário, o que pode causar problemas de acessibilidade. É importante testar a tipografia fluida com zoom e revertê-la para a tipografia responsiva normal se o teste revelar que o conteúdo não tem zoom suficiente.
Devemos ser capazes de resolver esse problema substituindo os valores de tipografia fluida quando ocorre uma ação de zoom. No entanto, atualmente não é possível fazer isso, pois a API Visual Viewport não está funcionando corretamente e não responde aos eventos de zoom do usuário.
Referências
-
clamp()
, MDN - “Por que o tipo deve ser fluido, afinal?”, Elise Hein
- “Tipografia de fluido simplificada”, Chris Coyier
- “Tipo responsivo e zoom”, Adrian Roselli
- “Tipografia responsiva e fluida com unidades
vh
evw
”, Michael Riethmuller