Programação Por Equipe DevBras

Capa do artigo: Tabela larga no celular: rolagem com nome ou ficha por linha, sem espremer

Tabela larga no celular: rolagem com nome ou ficha por linha, sem espremer

Escolha entre rolagem horizontal acessível e layout de fichas, mantenha cabeçalho ligado a cada valor e teste no telefone se ainda dá para saber de qual coluna é o número.

O relatório "Vendas por loja" tem oito colunas: loja, pedidos, faturamento, ticket médio, devoluções, frete, margem e variação. No desktop, perfeito. No celular do gerente regional, cada coluna ficou com 40 pixels de largura, os números quebraram em três linhas e "R$ 18.430,00" virou "R$ / 18.430 / ,00".

A resposta curta: não esprema a tabela. Você tem dois caminhos honestos. Se a pessoa precisa comparar linhas, deixe a tabela com largura natural dentro de uma área de rolagem horizontal com nome, mantendo a primeira coluna fixa. Se cada linha é lida isoladamente, transforme cada linha numa ficha que repete o nome de cada campo ao lado do valor. Os dois preservam a pergunta "de qual coluna é este número?".

Por que a tabela espreme

Tabela HTML tenta caber no contêiner. Quando o espaço acaba, o navegador reduz as colunas até o limite da palavra mais longa de cada uma e quebra o resto. Com width: 100% num contêiner de 360 pixels, oito colunas ficam com uns 45 pixels cada, descontado o espaçamento. Números longos quebram em pontos que destroem o sentido.

Quando o texto não pode quebrar, o problema muda de lugar: a tabela estoura a página e o layout inteiro passa a rolar para o lado, incluindo cabeçalho e menu. A pessoa rola para ver a coluna "margem" e perde a coluna "loja". Ela vê 23% e não sabe de qual loja é.

Qual caminho escolher

  • Rolagem horizontal quando o valor está na comparação: ranking de lojas, extrato, planilha de preços. A pessoa precisa ver a coluna inteira de cima a baixo.
  • Fichas quando cada linha é um objeto: lista de pedidos, cadastro de clientes, chamados. A pessoa lê um registro de cada vez.
  • Menos colunas sempre que possível: pergunte se o celular precisa das oito. Às vezes a versão móvel mostra três colunas e um link para o detalhe.

Como fazer a rolagem horizontal acessível

  1. Envolva a tabela num contêiner com overflow-x: auto. Só a tabela rola, o resto da página fica parado.
  2. Dê ao contêiner role="region", um nome via aria-labelledby apontando para a legenda e tabindex="0", para quem usa teclado conseguir focar e rolar com as setas.
  3. Use caption como título da tabela, th scope="col" no cabeçalho e th scope="row" na primeira célula de cada linha.
  4. Impeça a quebra de números com white-space: nowrap e defina uma largura mínima para a tabela.
  5. Fixe a primeira coluna com position: sticky e fundo opaco.
  6. Deixe visível que há mais conteúdo: a última coluna cortada pela metade já sinaliza, ou um texto curto acima da tabela.
<div class="rolagem-tabela" role="region" aria-labelledby="cap-vendas" tabindex="0">
  <table>
    <caption id="cap-vendas">Vendas por loja, setembro de 2026</caption>
    <thead>
      <tr>
        <th scope="col">Loja</th>
        <th scope="col">Pedidos</th>
        <th scope="col">Faturamento</th>
        <th scope="col">Margem</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Centro</th>
        <td>412</td>
        <td>R$ 18.430,00</td>
        <td>23%</td>
      </tr>
    </tbody>
  </table>
</div>
.rolagem-tabela {
  overflow-x: auto;
  max-width: 100%;
}
.rolagem-tabela:focus-visible {
  outline: 3px solid #1a5fb4;
  outline-offset: 2px;
}
.rolagem-tabela table {
  border-collapse: collapse;
  min-width: 44rem;
}
.rolagem-tabela th,
.rolagem-tabela td {
  padding: 0.5rem 0.75rem;
  white-space: nowrap;
  text-align: right;
}
.rolagem-tabela th[scope="row"] {
  position: sticky;
  left: 0;
  background: #fff;
  text-align: left;
}

O fundo branco na coluna fixa é obrigatório: sem ele, os números das outras colunas passam por baixo e aparecem através do nome da loja. Se você também quer o cabeçalho fixo ao rolar na vertical, a técnica e os motivos pelos quais o sticky às vezes não gruda estão em cabeçalho fixo de tabela.

Como fazer o layout de fichas

Para a lista de pedidos, cada linha vira um bloco. A tabela continua sendo tabela no HTML, e o CSS muda a apresentação só em telas estreitas. Cada célula carrega o nome da coluna num atributo, que o CSS mostra antes do valor.

<td data-rotulo="Faturamento">R$ 18.430,00</td>
@media (max-width: 40rem) {
  .tabela-fichas thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .tabela-fichas tr {
    display: block;
    border: 1px solid #ccc;
    border-radius: 6px;
    margin-bottom: 0.75rem;
    padding: 0.5rem;
  }
  .tabela-fichas td,
  .tabela-fichas th[scope="row"] {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
  }
  .tabela-fichas td::before {
    content: attr(data-rotulo);
    font-weight: 600;
  }
}

Um alerta importante: mudar o display de elementos de tabela pode fazer alguns navegadores deixarem de expor a estrutura de tabela para leitores de tela. Teste com o leitor de tela do aparelho. Se a estrutura sumir, uma saída conhecida é reforçar com papéis ARIA explícitos (role="table", role="row", role="cell", role="columnheader"). Outra é gerar fichas de verdade, com lista e rótulos no HTML, quando o conteúdo não é comparativo.

Também note que o cabeçalho foi escondido só visualmente, e não com display: none, para continuar disponível a tecnologias assistivas.

O que não fazer

Trocar a tabela por um amontoado de div para "facilitar o responsivo" é o erro mais caro. Você perde a associação entre cabeçalho e célula, perde a navegação por tabela do leitor de tela e passa a manter dois layouts manualmente. Se o conteúdo é tabular, o HTML é table. A partir daí, a decisão de layout é do CSS, escrito primeiro para o celular como mostra CSS mobile-first.

Erros comuns

  • Deixar a tabela com width: 100% e oito colunas. Os valores quebram em pedaços e "R$ 18.430,00" vira três linhas ilegíveis.
  • Página inteira rolando para o lado. Menu e cabeçalho somem junto, e a pessoa se perde na própria tela.
  • Coluna fixa sem fundo. O conteúdo que rola aparece por baixo do nome e nenhum dos dois se lê.
  • Área de rolagem sem foco nem nome. Quem usa teclado não consegue rolar e o leitor de tela não sabe o que é aquela região.
  • Esconder o cabeçalho com display: none. A associação entre valor e coluna desaparece para quem não enxerga.
  • Testar só no modo responsivo do desktop. Rolagem com o dedo, largura real e leitor de tela do aparelho se comportam diferente.

Checklist

  • Cada tabela larga foi classificada como comparativa (rolagem) ou de registros (fichas).
  • A tabela tem caption, th scope="col" e th scope="row".
  • Só o contêiner da tabela rola na horizontal, não a página.
  • O contêiner de rolagem tem nome, role="region" e é focável.
  • Números não quebram linha.
  • A primeira coluna fica fixa com fundo opaco.
  • No layout de fichas, todo valor aparece com o nome da coluna.
  • O resultado foi conferido no telefone com o leitor de tela ligado.

Abra no celular a tabela mais larga do seu sistema e role até a última coluna. Você ainda consegue dizer, sem voltar, a qual linha e a qual coluna pertence o número que está vendo?

Avalie este artigo

Referência: https://www.w3.org/WAI/tutorials/tables/