CSS / Truncar texto em uma ou várias linhas com reticências

Para encurtar visualmente textos longos com CSS, use text-overflow: ellipsis para uma linha única e propriedades line-clamp para limitar múltiplas linhas. O CSS não exclui a string original nem retorna um número fixo de caracteres. Largura disponível, quebra de linha e overflow devem funcionar juntos para que a truncagem apareça.

Distinguir o corte visual da alteração da string

Limitar um título a uma linha ou o resumo de um cartão a três linhas difere de usar os primeiros 20 caracteres como dado. Use CSS para o limite visual e JavaScript ou processamento no lado do servidor para uma operação real de string. O texto oculto permanece no documento, portanto o CSS não reduz o tamanho original dos dados nem o tamanho de transferência.

Objetivo Abordagem apropriada
Reticências no final de uma linha Largura limitada + nowrap + overflow + text-overflow
Reticências após várias linhas Limite de linhas + as configurações necessárias de exibição, direção e overflow
Uma string com limite real de comprimento Processamento em JavaScript ou no lado do servidor

Comparar uma e três linhas com um exemplo completo

Salve o código completo abaixo como truncate.html em UTF-8 e abra-o em um navegador. Nenhuma biblioteca ou servidor é necessário. A frase repetida torna o texto suficientemente longo, e o cartão tem largura máxima de 24rem. Salve e recarregue após editar, então compare janelas mais largas e mais estreitas.

<!DOCTYPE html>

<html lang="pt">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<title>Comparar texto truncado em uma e várias linhas</title>
<style>
    body { max-width: 42rem; margin: 0 auto; padding: 1rem; font-family: sans-serif; }
    h2 { font-size: 1.1rem; }
    .card { width: 100%; max-width: 24rem; }
    .frame { padding: 12px; border: 1px solid #777; margin-block: 1rem; }
    .sample { margin: 0; }
    .one { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
    .three { font-size: 16px; line-height: 1.6; max-height: 4.8em; overflow: hidden;
      display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; }
    .row { display: flex; align-items: center; gap: 12px; }
    .grow { flex: 1; min-width: 0; }
    .badge { flex: 0 0 auto; }
    .full { line-height: 1.6; overflow-wrap: anywhere; }
  </style>
</head>
<body>
<h1>Comparar texto truncado em uma e várias linhas</h1>
<div class="card">
<h2>text-overflow: ellipsis</h2>
<div class="frame"><p class="sample one">Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. </p></div>
<h2>-webkit-line-clamp: 3</h2>
<div class="frame"><p class="sample three">Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. </p></div>
<h2>display: flex</h2>
<div class="frame row"><div class="grow"><p class="sample one">Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. </p></div><span class="badge">A</span></div>
<details>
<summary>Ler o texto completo</summary>
<p class="sample full">Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. Este exemplo mostra um título e um resumo longos em um cartão limitado. Mesmo quando parte do texto fica oculta, a passagem completa está disponível na seção expansível abaixo. </p>
</details>
</div>
</body>
</html>

Espere truncamento de uma linha na primeira caixa, no máximo três linhas na segunda onde suportado, e truncamento de uma linha dentro do Flexbox na terceira. Abra a seção expansível abaixo para ler a passagem completa. Texto curto pode nunca atingir um limite e, portanto, não mostrar reticências. A quebra real depende da fonte, do conteúdo e da largura disponível.

Condições para reticências em uma linha

A truncagem em uma única linha requer que o texto ultrapasse seu espaço horizontal. white-space: nowrap impede a quebra de linha, overflow: hidden oculta o excesso e text-overflow: ellipsis marca o final cortado. A seguir está a regra .one do exemplo completo.

.one {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

Definir apenas text-overflow não força o transbordamento nem torna a caixa mais estreita. O cartão pai restringe a largura aqui. Se uma caixa continuar crescendo com seu conteúdo, ou se o texto for suficientemente curto, nenhuma reticência aparecerá. Elementos inline comuns podem não se comportar como esperado; verifique a caixa de bloco e o contexto real de layout. explicação do text-overflow da MDN

Limitar várias linhas e definir uma altura alternativa

Adicionar apenas text-overflow: ellipsis não coloca uma reticência no final da terceira linha. O exemplo combina as declarações de compatibilidade legada -webkit-line-clamp: 3, display: -webkit-box e -webkit-box-orient: vertical, juntamente com overflow oculto. A seguir está sua regra .three.

.three {
  font-size: 16px;
  line-height: 1.6;
  max-height: 4.8em;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

Com font-size de 16px e line-height de 1.6 aqui, uma linha tem 25,6px de altura e três linhas ocupam 76,8px, ou 4,8em. max-height: 4.8em limita a altura mesmo se o clamp não estiver disponível. Um limite de altura sozinho não garante uma reticência. Este cálculo assume o tamanho de fonte e a altura de linha consistentes do exemplo, sem padding ou borda separada no elemento de texto.

A propriedade line-clamp sem prefixo tem suporte variável entre navegadores, então verifique a tabela de suporte e a renderização nos seus ambientes-alvo. Aplique-a progressivamente com uma consulta de recurso quando apropriado, e verifique o suporte antes de substituir as declarações de compatibilidade. Para comparar duas linhas, altere tanto a contagem de clamp quanto a altura de fallback para 2 e 3,2em, depois restaure os valores originais. Informações de compatibilidade e suporte ao line-clamp

Quando elementos não encolhem no Flexbox ou Grid

A largura mínima automática de um item flex pode mantê-lo preso ao tamanho do conteúdo, impedindo encolhimento suficiente à medida que o pai diminui. O exemplo dá a .grow tanto flex: 1 quanto min-width: 0 para que ele possa encolher. Aplique o truncamento a .one, que na verdade contém o texto.

Remova temporariamente a min-width de .grow nas ferramentas de desenvolvedor, compare e restaure-a. Isso não é um requisito universal para cada item flex; inspecione o tamanho mínimo real e as condições de estouro. Para problemas automáticos de tamanho mínimo em Grid, verifique o min-width do item e considere uma definição de trilha flexível como minmax(0, 1fr) quando apropriado. Explicação da MDN sobre tamanhos mínimos automáticos em min-width

Oferecer acesso ao texto completo

Forneça uma maneira de ler o conteúdo oculto. Os elementos details e summary do exemplo são elementos HTML nativos que funcionam com mouse, toque e teclado sem JavaScript. Uma interface real pode, em vez disso, fornecer um link para a página de detalhes ou outro controle de expansão claro.

  1. Não confie em uma dica de ferramenta de mouse com atributo title como a única forma de ler o conteúdo completo. Usuários de toque e teclado também precisam de acesso.
  2. Como o texto oculto é exibido quando copiado ou lido por tecnologias assistivas pode variar. Verifique se o texto necessário continua legível e se o foco funciona no controle de expansão.
  3. Verifique telas móveis, zoom e fontes selecionadas pelo usuário. Não prometa uma contagem fixa de caracteres ou palavras e evite aplicar corte em informações essenciais, botões ou campos de entrada.