Como fazer pro texto não quebrar de linha no CSS

Camilo Micheletto - May 6 '23 - - Dev Community

Se você desenvolve layouts no seu dia-a-dia, o causo da imagem abaixo já aconteceu com você

Imagem de um chat entre duas pessoas. A pessoa um diz "puta que pariu caralho", a pessoa 2 responde com "?", a pessoa 1 então manda uma imagem de um botão em que o texto interno está quebrando em duas linhas com a frase "essa porra quebra de linha", ao que a pessoa 2 responde "tentou white-space?"

 

E geralmente te recomendam uma dessas soluções:

  • width: 100%
  • word-break
  • white-space

Mas muito provavelmente seu problema não tem nada a ver com nenhuma dessas 3 propriedades.

Nesse artigo eu vou explicar porque esse problema acontece e como o navegador entende quebras de linha.


O real problema

Se você adicionar estilo nenhum no elemento, o valor padrão da width dele será "auto".

A width de "auto" primeiro faz a soma da largura total do seu conteúdo + border + margin-inline + padding-inline. Se a soma disso for menor que o espaço disponível, a width vai ocupar todo espaço disponível, mas se for menor que o espaço disponível, ela vai procurar oportunidades de soft wrap (ou quebra fofo), ou seja caracteres de espaço (U+0020) e sinalizadores de quebra de linha (U+000D).

O algoritmo que aplica soft-wrap de acordo com o tamanho do container que é o que provavelmente decidiu por você que seu texto não cabe em 1 linha só.

Isso é um problema de width que pode ser resolvido com intrinsic-sizing!

A propriedade width: max-content vai dizer que o container tem que ser no mínimo do tamanho do conteúdo.

Eu falo bem mais detalhadamente nesse meu artigo sobre intrinsic sizing:

 

width: 100%; pode não só não resolver como quebrar o seu layout!
Isso se deve ao fato de que os 100% são aplicados apenas ao conteúdo, a largura final vai ser somada à largura do padding, margin e border, "estourando" seu conteúdo horizontalmente.

Imagem de dois containers, um com width de auto e outro com width de 100%, o segundo com overflow por causa da propriedade
Imagem por Ahmad Hadeed no seu artigo Everything About Auto in CSS

 


E as outras propriedades?

Elas basicamente usam da engine do navegador que lida com espaço em branco. Whitespace (pra ser curto) é de extrema importância pro navegador - ela é responsável por manter algumas tabulações da sua identação, espaço entre palavras, mas se você escreve algo como exemplo abaixo com espaçamento escagalhado, ela interpreta corretamente os espaços, tabulações e quebras de linha que tem que ignorar.

Um h1 contendo uma palavra Hello e um span com a palavra World! com muitos excessos de espaçamento e tabulação
Print retirado do artigo How whitespace is handled by HTML, CSS, and in the DOM da MDN

 

Daqui pra baixo é nerdagem, então TL:DR
Essas propriedades basicamente chupinham da lógica de quebra de espaço do navegador

 


O navegador e o algoritmo de whitespace

Quando o whitespace _é delimitado pra elementos inline (TextNodes, <span>, <input>, etc), o navegador cria um contexto específico pra eles chamado _Inline Formatting Context (vou chamar de IFC).

O IFC calcula as quebras de espaço e também coordena eixo de leitura text-orientation

O IFC lida com espaçamentos da seguinte forma

<!-- Legenda
  ◦ - espaço
  ⇥ - tabulação
  ⏎ - quebra de linha
-->
<!-- Primeiro, espaços e tabs imediatamente antes
e depois de uma quebra de linha são ignorados,
então se pegarmos o exemplo abaixo... -->

<h1>◦◦◦Hello◦⏎
⇥⇥⇥⇥<span>◦World!</span>⇥◦◦</h1>

<!-- ...e aplicar essa regra, nós temos: -->

<h1>◦◦◦Hello⏎
<span>◦World!</span>⇥◦◦</h1>

<!-- A seguir, todos os caracteres de tab são
transformados em caracteres de tab, então
o exemplo fica da seguinte maneira: -->

<h1>◦◦◦Hello⏎
<span>◦World!</span>◦◦◦</h1>


<!-- Em seguida, quebras de linhas também são
convertidas em espaços: -->

<h1>◦◦◦Hello◦<span>◦World!</span>◦◦◦</h1>

<!-- Após isso, qualquer espaço seguido imediatamente
de outro espaço (mesmo entre dois elementos separados)
é ignorado, nos deixando com o seguinte: -->

<h1>◦Hello◦<span>World!</span></h1>

<!-- E finalmente, espaços no começo e no fim
do elemento são removidos, nos resultando isso: -->

<h1>Hello◦<span>World!</span></h1>

Enter fullscreen mode Exit fullscreen mode

Transcrito da publicação How whitespace is handled by HTML, CSS, and in the DOM, traduzido por mim.

 

💡 Inclusive, traduzi usando o designMode do navegador, é tipo um contenteditable. Não sabe o que é isso? Leia essa thread do @omariosouto no Twitter

 


A propriedade white-space

O white-space usa esse algoritmo pra calcular as "soft wrap opportunities" que são espaços e tabs, mas também quebras de palavras se a propriedade hyphens: auto; estiver presente pro elemento.

Essa propriedade também aplica hífen em quebras de palavras de acordo com o atributo lang do seu HTML.

Quais são os valores aceitos pelo white-space?

Valor Novas Linhas Espaçoes e tabulações Quebra de texto
normal Recolhido Recolhido Quebra
nowrap Recolhido Recolhido Sem quebra
pre Preservado Preservado Sem quebra
pre-wrap Preservado Preservado Quebra
pre-line Preservado Recolhido Quebra
break-spaces Preservado Preservado Quebra

Tabela transcrita da documentação do white-space na MDN, em inglês, pois a em português está terrivelmente desatualizada.

 

Aplicadas, essas propriedades se comportam da seguinte maneira:
Textos com diferentes aplicações de white-space


A propriedade word-break

Essa propriedade define como o navegador vai calcular o agrupamento de caracteres, quais são quebráveis por hyphens ou soft wrap opportunities, especialmente necessário em caracteres CJK (Chinese, Japanese, Korean).

Os valores de word-break são normal, keep-all e break-all.

  • normal
    Quebra de linha padrão

  • keep-all
    Não permite quebra nenhuma pra caracteres CKJ, mas age como normal pra outros caracteres.

  • break-all
    Vai inserir quebra em qualquer espaço entre caracteres, mesmo CKJ.

⛔ Geralmente, pra resolver o problema de quebra de linha, sugerem essa propriedade ao invés de white-space e a maioria das vezes não funciona, agora entende o porquê?

 

Exemplos de word-break
word-break: break-word omitido por estar depreciado


A propriedade overflow-wrap

Ele não cuida do espaço em branco, nem dos soft wraps e hifenações entre palavras, ele cuida da lógica que o container pai usa pra decidir se as palavras dentro dele devem quebrar de linha ou não.

É basicamente o mesmo algoritmo que intrinsic sizing utiliza!

Os seus valores são normal, anywhere e break-word

  • normal
    É o comportamento normal - quebra em soft wraps se o texto não couber no container.

  • anywhere
    Vai quebrar todas as palavras em soft wraps, e na ausência deles só vai quebrar msm, e sem hífen ein!

  • break-word (antigamente valor da propriedade word-break)
    Vai funcionar que nem o anywhere mas vai manter palavras na mesma linha se elas couberem.

Eles funcionam mais ou menos como width: max-content, min-content e fit-content, respectivamente;

Demonstração de overflow-wrap

 

TL;DR

O white-space controla o algoritmo que o navegador utiliza pra lidar com espaço em branco.
O word-break lida com como o navegador coordena o agrupamento de caracteres de acordo com hifenação e linguagem.
O overflow-wrap lida como o elemento coordena o conteúdo de acordo com seu tamanho intrínseco.


E por hoje é isso!

E ai, vocês já tiveram esse tipo de problema? Como resolveram?
Espero que tenha ajudado algumas pessoas a chutar menos!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .