Linhas de texto com largura igual

Os bloqueios em estilo de pôster, em que cada linha é dimensionada para abranger toda a largura do contêiner, podem criar títulos visualmente impressionantes. Usando text-fit, o navegador dimensiona cada linha durante o layout, para que ela permaneça correta ao redimensionar, copiar alterações e carregar fontes.

Para uma única linha que preenche o contêiner (por exemplo, um título ou uma citação), aplique text-fit diretamente a esse elemento. Este guia aborda os bloqueios de várias linhas.

Implementação básica

Para linhas forçadas:

  • Envolva cada linha em um <span> com display: block.
  • Aplique white-space: nowrap a cada linha forçada <span>.

Diretrizes de implementação:

  • Use text-fit: grow per-line-all <percentage> no próprio cabeçalho.
  • Use per-line-all, não per-line. per-line ignora a última linha e qualquer linha que termine com uma quebra forçada. Portanto, com um bloco por linha, ele não dimensiona nada.
  • grow não pode ser combinado com shrink. Defina o font-size base como um máximo ou um mínimo, dependendo do que seria um substituto melhor ou mais fácil de calcular, e defina text-fit como shrink ou grow, conforme apropriado. Se você não tiver um motivo para usar shrink, prefira grow + definir font-size como mínimo, já que é mais seguro na maioria dos casos.
  • Sempre limite o crescimento ou a redução com a porcentagem (por exemplo, 300%) como uma proteção.
  • O contêiner precisa de um tamanho inline definido. text-fit nunca muda o tamanho intrínseco, então não faz nada em larguras fit-content/max-content ou itens flexíveis/de grade com tamanho de conteúdo.
  • Corte o espaçamento acima da primeira linha e abaixo da última: consulte Alinhamento de texto preciso.
  • Mantenha o line-height pequeno, 1 ou menos. Caso contrário, as lacunas entre as linhas de diferentes tamanhos de fonte vão ficar difíceis de gerenciar.
  • IMPORTANTE: o font-size calculado não muda, então o espaçamento de em não é dimensionado.
  • Para evitar órfãos acidentalmente enfatizados, aplique text-wrap: balance ou text-wrap: pretty se houver linhas livres.

Espaçamento

Se todas as linhas forem forçadas, isso vai produzir mais controle sobre o espaçamento:

  • Aplique text-box: trim-both cap alphabetic a cada bloco de linha para que a caixa se ajuste aos próprios glifos. Ele faz o corte usando as métricas escalonadas. Consulte Alinhamento de texto preciso para mais detalhes.
  • Espaçar linhas usando Flexbox ou Grid + gap no cabeçalho, não line-height. Assim, os espaços ficam uniformes em vez de aumentar com o tamanho da fonte de cada linha.

Se algumas linhas estiverem livres, não use text-box: ele só corta a primeira e a última linha, então as linhas externas vão abraçar os glifos, enquanto as lacunas internas mantêm o espaçamento. Deixe que o line-height controle todo o espaçamento.

Design visual

  • Os lockups ficam melhores quando há uma variação significativa nos tamanhos de fonte entre as linhas. Evite criar lockups com textos que tenham linhas de tamanho uniforme, porque isso vai resultar em tamanhos de fonte que não são iguais nem suficientemente diferentes, violando o princípio de design de contraste. Para garantir isso, force linhas curtas: coloque as palavras que quer enfatizar em um bloco e deixe o restante em outro, ou seja, um lockup misto. Isso é especialmente importante ao combinar com text-wrap: balance.
  • Combine isso com text-transform: uppercase ao usar scripts ocidentais, já que as letras ascendentes e descendentes tendem a criar espaços presos e/ou sobrepor linhas adjacentes, o que cria um resultado menos estético.
  • Ao forçar linhas curtas, escolha palavras que melhorem a mensagem se forem enfatizadas.
  • Limitação: o texto em crescimento também vai aumentar em peso visual, e os traços vão parecer mais fortes. No momento, não há como compensar isso, por exemplo, reduzindo font-weight para textos maiores, já que não há unidade para usar em um cálculo, porque o dimensionamento não afeta unidades relativas à fonte, como em.

Estratégias de fallback

Para text-box

text-box não precisa de um substituto separado: mantenha o line-height pequeno também em bloqueios fixos. É uma operação sem efeito em text-box e mantém os espaços pequenos onde não há suporte, ao custo de espaços que se ajustam ao tamanho da fonte de cada linha.

Para text-wrap: balance

Para text-fit

As linhas forçadas têm um substituto curto e fiel: meça cada linha no tamanho base e dimensione-a pela proporção em relação ao contêiner, com o mesmo limite.

@supports not (text-fit: grow) {
  .lockup > span {
    /* Shrink-wrap each line so its width is the text width */
    width: fit-content;
    /* --text-fit-scale is measured by the script; the cap mirrors the text-fit percentage */
    font-size: min(var(--text-fit-scale, 1) * 1em, 300%);
  }
}
if (!CSS.supports('text-fit', 'grow per-line-all')) {
  const fit = lockup => {
    const lines = [...lockup.querySelectorAll(':scope > span')];
    // Unscale first: on a refit, offsetWidth would otherwise include the previous scale
    for (const line of lines) line.style.removeProperty('--text-fit-scale');
    // MANDATORY: all reads, then all writes. Interleaving them (e.g. reading
    // lockup.clientWidth inside the write loop) forces one reflow per line.
    const scales = lines.map(line => lockup.clientWidth / line.offsetWidth);
    lines.forEach((line, i) => line.style.setProperty('--text-fit-scale', scales[i]));
  };
  // Refit on resize and font load
  for (const lockup of document.querySelectorAll('.lockup')) {
    new ResizeObserver(() => fit(lockup)).observe(lockup);
  }
}

As linhas livres não têm um substituto fiel (as quebras de linha são desconhecidas até o layout): aprimoramento progressivo para um título equilibrado com um tamanho de base fluido, como clamp(2rem, 1rem + 5cqi, 5rem). Em um lockup misto, o script acima ainda se ajusta às linhas forçadas. Um bloco de quebra de linha mede a largura do contêiner, então ele mantém a escala 1 e recebe apenas o tamanho de base fluido.

Se o ajuste de texto for essencial, use uma biblioteca JS (por exemplo, fitty), carregada condicionalmente apenas se text-fit não for compatível.